001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: NodeIteratorBase.java 468651 2006-10-28 07:04:25Z minchau $
020 */
021
022 package org.apache.xalan.xsltc.dom;
023
024 import org.apache.xalan.xsltc.NodeIterator;
025 import org.apache.xalan.xsltc.runtime.BasisLibrary;
026
027 /**
028 * @author Jacek Ambroziak
029 * @author Santiago Pericas-Geertsen
030 * @author Morten Jorgensen
031 */
032 public abstract class NodeIteratorBase implements NodeIterator {
033
034 /**
035 * Cached computed value of last().
036 */
037 protected int _last = -1;
038
039 /**
040 * Value of position() in this iterator. Incremented in
041 * returnNode().
042 */
043 protected int _position = 0;
044
045 /**
046 * Store node in call to setMark().
047 */
048 protected int _markedNode;
049
050 /**
051 * Store node in call to setStartNode().
052 */
053 protected int _startNode = NodeIterator.END;
054
055 /**
056 * Flag indicating if "self" should be returned.
057 */
058 protected boolean _includeSelf = false;
059
060 /**
061 * Flag indicating if iterator can be restarted.
062 */
063 protected boolean _isRestartable = true;
064
065 /**
066 * Setter for _isRestartable flag.
067 */
068 public void setRestartable(boolean isRestartable) {
069 _isRestartable = isRestartable;
070 }
071
072 /**
073 * Initialize iterator using a node. If iterator is not
074 * restartable, then do nothing. If node is equal to END then
075 * subsequent calls to next() must return END.
076 */
077 abstract public NodeIterator setStartNode(int node);
078
079 /**
080 * Reset this iterator using state from last call to
081 * setStartNode().
082 */
083 public NodeIterator reset() {
084 final boolean temp = _isRestartable;
085 _isRestartable = true;
086 // Must adjust _startNode if self is included
087 setStartNode(_includeSelf ? _startNode + 1 : _startNode);
088 _isRestartable = temp;
089 return this;
090 }
091
092 /**
093 * Setter for _includeSelf flag.
094 */
095 public NodeIterator includeSelf() {
096 _includeSelf = true;
097 return this;
098 }
099
100 /**
101 * Default implementation of getLast(). Stores current position
102 * and current node, resets the iterator, counts all nodes and
103 * restores iterator to original state.
104 */
105 public int getLast() {
106 if (_last == -1) {
107 final int temp = _position;
108 setMark();
109 reset();
110 do {
111 _last++;
112 } while (next() != END);
113 gotoMark();
114 _position = temp;
115 }
116 return _last;
117 }
118
119 /**
120 * Returns the position() in this iterator.
121 */
122 public int getPosition() {
123 return _position == 0 ? 1 : _position;
124 }
125
126 /**
127 * Indicates if position in this iterator is computed in reverse
128 * document order. Note that nodes are always returned in document
129 * order.
130 */
131 public boolean isReverse() {
132 return false;
133 }
134
135 /**
136 * Clones and resets this iterator. Note that the cloned iterator is
137 * not restartable. This is because cloning is needed for variable
138 * references, and the context node of the original variable
139 * declaration must be preserved.
140 */
141 public NodeIterator cloneIterator() {
142 try {
143 final NodeIteratorBase clone = (NodeIteratorBase)super.clone();
144 clone._isRestartable = false;
145 return clone.reset();
146 }
147 catch (CloneNotSupportedException e) {
148 BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
149 e.toString());
150 return null;
151 }
152 }
153
154 /**
155 * Utility method that increments position and returns its
156 * argument.
157 */
158 protected final int returnNode(final int node) {
159 _position++;
160 return node;
161 }
162
163 /**
164 * Reset the position in this iterator.
165 */
166 protected final NodeIterator resetPosition() {
167 _position = 0;
168 return this;
169 }
170 }