001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.xpath.iterators; 021 022import java.util.ArrayDeque; 023import java.util.Queue; 024 025import net.sf.saxon.om.NodeInfo; 026import net.sf.saxon.om.SequenceIterator; 027import net.sf.saxon.tree.iter.SingletonIterator; 028 029/** 030 * Recursive-free implementation of the descendant axis iterator. 031 */ 032public class DescendantIterator implements SequenceIterator { 033 034 /** 035 * Enum defines starting node for iterator. 036 */ 037 public enum StartWith { 038 039 /** Start with current node. */ 040 CURRENT_NODE, 041 /** Omit current node and start with child nodes. */ 042 CHILDREN, 043 044 } 045 046 /** 047 * Queue for sibling nodes. 048 */ 049 private final Queue<NodeInfo> queue = new ArrayDeque<>(); 050 /** 051 * Descendant axis iterator. 052 */ 053 private SequenceIterator descendantEnum; 054 055 /** 056 * Create an iterator over the "descendant" axis. 057 * 058 * @param start the initial context node. 059 * @param startWith mode of the iterator, see {@link StartWith}. 060 */ 061 public DescendantIterator(NodeInfo start, StartWith startWith) { 062 if (startWith == StartWith.CURRENT_NODE) { 063 descendantEnum = SingletonIterator.makeIterator(start); 064 } 065 else if (startWith == StartWith.CHILDREN) { 066 descendantEnum = start.iterateChildAxis(null); 067 } 068 } 069 070 /** 071 * Get the next item in the sequence. 072 * 073 * @return the next Item. If there are no more nodes, return null. 074 */ 075 @Override 076 public NodeInfo next() { 077 NodeInfo result = null; 078 do { 079 if (descendantEnum == null) { 080 if (queue.isEmpty()) { 081 break; 082 } 083 descendantEnum = queue.poll().iterateChildAxis(null); 084 } 085 else { 086 result = (NodeInfo) descendantEnum.next(); 087 if (result == null) { 088 descendantEnum = null; 089 } 090 } 091 } while (result == null); 092 093 if (result != null) { 094 queue.add(result); 095 } 096 return result; 097 } 098 099}