001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2024 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.LinkedList; 023import java.util.Queue; 024 025import net.sf.saxon.om.AxisInfo; 026import net.sf.saxon.om.NodeInfo; 027import net.sf.saxon.tree.iter.AxisIterator; 028import net.sf.saxon.tree.iter.SingleNodeIterator; 029 030/** 031 * Recursive-free implementation of the descendant axis iterator. 032 */ 033public class DescendantIterator implements AxisIterator { 034 035 /** 036 * Enum defines starting node for iterator. 037 */ 038 public enum StartWith { 039 /** Start with current node. */ 040 CURRENT_NODE, 041 /** Omit current node and start with child nodes. */ 042 CHILDREN, 043 } 044 045 /** 046 * Queue for sibling nodes. 047 */ 048 private final Queue<NodeInfo> queue = new LinkedList<>(); 049 /** 050 * Descendant axis iterator. 051 */ 052 private AxisIterator descendantEnum; 053 054 /** 055 * Create an iterator over the "descendant" axis. 056 * 057 * @param start the initial context node. 058 * @param startWith mode of the iterator, see {@link StartWith}. 059 */ 060 public DescendantIterator(NodeInfo start, StartWith startWith) { 061 if (startWith == StartWith.CURRENT_NODE) { 062 descendantEnum = SingleNodeIterator.makeIterator(start); 063 } 064 else if (startWith == StartWith.CHILDREN) { 065 descendantEnum = start.iterateAxis(AxisInfo.CHILD); 066 } 067 } 068 069 /** 070 * Get the next item in the sequence. 071 * 072 * @return the next Item. If there are no more nodes, return null. 073 */ 074 @Override 075 public NodeInfo next() { 076 NodeInfo result = null; 077 do { 078 if (descendantEnum == null) { 079 if (queue.isEmpty()) { 080 break; 081 } 082 descendantEnum = queue.poll().iterateAxis(AxisInfo.CHILD); 083 } 084 else { 085 result = descendantEnum.next(); 086 if (result == null) { 087 descendantEnum = null; 088 } 089 } 090 } while (result == null); 091 092 if (result != null) { 093 queue.add(result); 094 } 095 return result; 096 } 097}