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: FilterIterator.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.runtime.BasisLibrary;
025    import org.apache.xml.dtm.DTMAxisIterator;
026    import org.apache.xml.dtm.DTMFilter;
027    import org.apache.xml.dtm.DTMIterator;
028    import org.apache.xml.dtm.ref.DTMAxisIteratorBase;
029    
030    /**
031     * Similar to a CurrentNodeListIterator except that the filter has a 
032     * simpler interface (only needs the node, no position, last, etc.)  
033     * It takes a source iterator and a Filter object and returns nodes 
034     * from the source after filtering them by calling filter.test(node).
035     * @author Jacek Ambroziak
036     * @author Santiago Pericas-Geertsen
037     */
038    public final class FilterIterator extends DTMAxisIteratorBase {
039    
040        /**
041         * Reference to source iterator.
042         */
043        private DTMAxisIterator _source;
044    
045        /**
046         * Reference to a filter object that to be applied to each node.
047         */
048        private final DTMFilter _filter;
049    
050        /**
051         * A flag indicating if position is reversed.
052         */
053        private final boolean _isReverse;
054            
055        public FilterIterator(DTMAxisIterator source, DTMFilter filter) {
056            _source = source;
057    // System.out.println("FI souce = " + source + " this = " + this);
058            _filter = filter;
059            _isReverse = source.isReverse();
060        }
061    
062        public boolean isReverse() {
063            return _isReverse;
064        }
065    
066    
067        public void setRestartable(boolean isRestartable) {
068            _isRestartable = isRestartable;
069            _source.setRestartable(isRestartable);
070        }
071    
072        public DTMAxisIterator cloneIterator() {
073    
074            try {
075                final FilterIterator clone = (FilterIterator) super.clone();
076                clone._source = _source.cloneIterator();
077                clone._isRestartable = false;
078                return clone.reset();
079            }
080            catch (CloneNotSupportedException e) {
081                BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
082                                          e.toString());
083                return null;
084            }
085        }
086        
087        public DTMAxisIterator reset() {
088            _source.reset();
089            return resetPosition();
090        }
091        
092        public int next() {
093            int node;
094            while ((node = _source.next()) != END) {
095                if (_filter.acceptNode(node, DTMFilter.SHOW_ALL) == DTMIterator.FILTER_ACCEPT) {
096                    return returnNode(node);
097                }
098            }
099            return END;
100        }
101    
102        public DTMAxisIterator setStartNode(int node) {
103            if (_isRestartable) {
104                _source.setStartNode(_startNode = node); 
105                return resetPosition();
106            }
107            return this;
108        }
109    
110        public void setMark() {
111            _source.setMark();
112        }
113    
114        public void gotoMark() {
115            _source.gotoMark();
116        }
117    
118    }