/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: CurrentNodeListIterator.java,v 1.13 2004/02/16 22:54:59 minchau Exp $ */ package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary; import com.sun.org.apache.xalan.internal.xsltc.util.IntegerArray; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase; /** * Iterators of this kind use a CurrentNodeListFilter to filter a subset of * nodes from a source iterator. For each node from the source, the boolean * method CurrentNodeListFilter.test() is called. * * All nodes from the source are read into an array upon calling setStartNode() * (this is needed to determine the value of last, a parameter to * CurrentNodeListFilter.test()). The method getLast() returns the last element * after applying the filter. * @author Jacek Ambroziak * @author Santiago Pericas-Geertsen * @author Morten Jorgensen */ public final class CurrentNodeListIterator extends DTMAxisIteratorBase { /** * A flag indicating if nodes are returned in document order. */ private boolean _docOrder; /** * The source for this iterator. */ private DTMAxisIterator _source; /** * A reference to a filter object. */ private final CurrentNodeListFilter _filter; /** * An integer array to store nodes from source iterator. */ private IntegerArray _nodes = new IntegerArray(); /** * Index in _nodes of the next node to filter. */ private int _currentIndex; /** * The current node in the stylesheet at the time of evaluation. */ private final int _currentNode; /** * A reference to the translet. */ private AbstractTranslet _translet; public CurrentNodeListIterator(DTMAxisIterator source, CurrentNodeListFilter filter, int currentNode, AbstractTranslet translet) { this(source, !source.isReverse(), filter, currentNode, translet); } public CurrentNodeListIterator(DTMAxisIterator source, boolean docOrder, CurrentNodeListFilter filter, int currentNode, AbstractTranslet translet) { _source = source; _filter = filter; _translet = translet; _docOrder = docOrder; _currentNode = currentNode; } public DTMAxisIterator forceNaturalOrder() { _docOrder = true; return this; } public void setRestartable(boolean isRestartable) { _isRestartable = isRestartable; _source.setRestartable(isRestartable); } public boolean isReverse() { return !_docOrder; } public DTMAxisIterator cloneIterator() { try { final CurrentNodeListIterator clone = (CurrentNodeListIterator) super.clone(); clone._nodes = (IntegerArray) _nodes.clone(); clone._source = _source.cloneIterator(); clone._isRestartable = false; return clone.reset(); } catch (CloneNotSupportedException e) { BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR, e.toString()); return null; } } public DTMAxisIterator reset() { _currentIndex = 0; return resetPosition(); } public int next() { final int last = _nodes.cardinality(); final int currentNode = _currentNode; final AbstractTranslet translet = _translet; for (int index = _currentIndex; index < last; ) { final int position = _docOrder ? index + 1 : last - index; final int node = _nodes.at(index++); // note increment if (_filter.test(node, position, last, currentNode, translet, this)) { _currentIndex = index; return returnNode(node); } } return END; } public DTMAxisIterator setStartNode(int node) { if (_isRestartable) { _source.setStartNode(_startNode = node); _nodes.clear(); while ((node = _source.next()) != END) { _nodes.add(node); } _currentIndex = 0; resetPosition(); } return this; } public int getLast() { if (_last == -1) { _last = computePositionOfLast(); } return _last; } public void setMark() { _markedNode = _currentIndex; } public void gotoMark() { _currentIndex = _markedNode; } private int computePositionOfLast() { final int last = _nodes.cardinality(); final int currNode = _currentNode; final AbstractTranslet translet = _translet; int lastPosition = _position; for (int index = _currentIndex; index < last; ) { final int position = _docOrder ? index + 1 : last - index; int nodeIndex = _nodes.at(index++); // note increment if (_filter.test(nodeIndex, position, last, currNode, translet, this)) { lastPosition++; } } return lastPosition; } }