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    }