1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xalan.internal.xsltc.dom; 23 24 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 25 import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary; 26 import com.sun.org.apache.xalan.internal.xsltc.util.IntegerArray; 27 import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 28 import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase; 29 30 /** 31 * Iterators of this kind use a CurrentNodeListFilter to filter a subset of 32 * nodes from a source iterator. For each node from the source, the boolean 33 * method CurrentNodeListFilter.test() is called. 34 * 35 * All nodes from the source are read into an array upon calling setStartNode() 36 * (this is needed to determine the value of last, a parameter to 37 * CurrentNodeListFilter.test()). The method getLast() returns the last element 38 * after applying the filter. 39 * @author Jacek Ambroziak 40 * @author Santiago Pericas-Geertsen 41 * @author Morten Jorgensen 42 */ 43 44 public final class CurrentNodeListIterator extends DTMAxisIteratorBase { 45 /** 46 * A flag indicating if nodes are returned in document order. 47 */ 48 private boolean _docOrder; 49 50 /** 51 * The source for this iterator. 52 */ 53 private DTMAxisIterator _source; 54 55 /** 56 * A reference to a filter object. 57 */ 58 private final CurrentNodeListFilter _filter; 59 60 /** 61 * An integer array to store nodes from source iterator. 62 */ 63 private IntegerArray _nodes = new IntegerArray(); 64 65 /** 66 * Index in _nodes of the next node to filter. 67 */ 68 private int _currentIndex; 69 70 /** 71 * The current node in the stylesheet at the time of evaluation. 72 */ 73 private final int _currentNode; 74 75 /** 76 * A reference to the translet. 77 */ 78 private AbstractTranslet _translet; 79 80 public CurrentNodeListIterator(DTMAxisIterator source, 81 CurrentNodeListFilter filter, 82 int currentNode, 83 AbstractTranslet translet) 84 { 85 this(source, !source.isReverse(), filter, currentNode, translet); 86 } 87 88 public CurrentNodeListIterator(DTMAxisIterator source, boolean docOrder, 89 CurrentNodeListFilter filter, 90 int currentNode, 91 AbstractTranslet translet) 92 { 93 _source = source; 94 _filter = filter; 95 _translet = translet; 96 _docOrder = docOrder; 97 _currentNode = currentNode; 98 } 99 100 public DTMAxisIterator forceNaturalOrder() { 101 _docOrder = true; 102 return this; 103 } 104 105 public void setRestartable(boolean isRestartable) { 106 _isRestartable = isRestartable; 107 _source.setRestartable(isRestartable); 108 } 109 110 public boolean isReverse() { 111 return !_docOrder; 112 } 113 114 public DTMAxisIterator cloneIterator() { 115 try { 116 final CurrentNodeListIterator clone = 117 (CurrentNodeListIterator) super.clone(); 118 clone._nodes = (IntegerArray) _nodes.clone(); 119 clone._source = _source.cloneIterator(); 120 clone._isRestartable = false; 121 return clone.reset(); 122 } 123 catch (CloneNotSupportedException e) { 124 BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR, 125 e.toString()); 126 return null; 127 } 128 } 129 130 public DTMAxisIterator reset() { 131 _currentIndex = 0; 132 return resetPosition(); 133 } 134 135 public int next() { 136 final int last = _nodes.cardinality(); 137 final int currentNode = _currentNode; 138 final AbstractTranslet translet = _translet; 139 140 for (int index = _currentIndex; index < last; ) { 141 final int position = _docOrder ? index + 1 : last - index; 142 final int node = _nodes.at(index++); // note increment 143 144 if (_filter.test(node, position, last, currentNode, translet, 145 this)) { 146 _currentIndex = index; 147 return returnNode(node); 148 } 149 } 150 return END; 151 } 152 153 public DTMAxisIterator setStartNode(int node) { 154 if (_isRestartable) { 155 _source.setStartNode(_startNode = node); 156 157 _nodes.clear(); 158 while ((node = _source.next()) != END) { 159 _nodes.add(node); 160 } 161 _currentIndex = 0; 162 resetPosition(); 163 } 164 return this; 165 } 166 167 public int getLast() { 168 if (_last == -1) { 169 _last = computePositionOfLast(); 170 } 171 return _last; 172 } 173 174 public void setMark() { 175 _markedNode = _currentIndex; 176 } 177 178 public void gotoMark() { 179 _currentIndex = _markedNode; 180 } 181 182 private int computePositionOfLast() { 183 final int last = _nodes.cardinality(); 184 final int currNode = _currentNode; 185 final AbstractTranslet translet = _translet; 186 187 int lastPosition = _position; 188 for (int index = _currentIndex; index < last; ) { 189 final int position = _docOrder ? index + 1 : last - index; 190 int nodeIndex = _nodes.at(index++); // note increment 191 192 if (_filter.test(nodeIndex, position, last, currNode, translet, 193 this)) { 194 lastPosition++; 195 } 196 } 197 return lastPosition; 198 } 199 }