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; 021 022import com.puppycrawl.tools.checkstyle.xpath.iterators.DescendantIterator; 023import net.sf.saxon.Configuration; 024import net.sf.saxon.om.GNode; 025import net.sf.saxon.om.GenericTreeInfo; 026import net.sf.saxon.om.NamespaceUri; 027import net.sf.saxon.om.NodeInfo; 028import net.sf.saxon.om.SequenceIterator; 029import net.sf.saxon.pattern.nodetest.NodePredicate; 030import net.sf.saxon.tree.iter.ArrayIterator; 031import net.sf.saxon.tree.iter.EmptyIterator; 032import net.sf.saxon.tree.iter.SingletonIterator; 033import net.sf.saxon.type.Type; 034 035/** 036 * Represents root node of Xpath-tree. 037 */ 038public abstract class AbstractRootNode extends AbstractNode { 039 040 /** Name of the root element. */ 041 private static final String ROOT_NAME = "ROOT"; 042 043 /** Constant for optimization. */ 044 private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0]; 045 046 /** 047 * Creates a new {@code AbstractRootNode} instance. 048 */ 049 protected AbstractRootNode() { 050 super(new GenericTreeInfo(Configuration.newConfiguration())); 051 } 052 053 /** 054 * Compares current object with specified for order. 055 * Throws {@code UnsupportedOperationException} because functionality not required here. 056 * 057 * @param other another {@code GNode} object 058 * @return number representing order of current object to specified one 059 */ 060 @Override 061 public int compareOrder(GNode other) { 062 throw throwUnsupportedOperationException(); 063 } 064 065 /** 066 * Returns attribute value. Throws {@code UnsupportedOperationException} because root node has 067 * no attributes. 068 * 069 * @param namespace namespace 070 * @param localPart actual name of the attribute 071 * @return attribute value 072 */ 073 @Override 074 public String getAttributeValue(NamespaceUri namespace, String localPart) { 075 throw throwUnsupportedOperationException(); 076 } 077 078 /** 079 * Returns local part. 080 * 081 * @return local part 082 */ 083 @Override 084 public String getLocalPart() { 085 return ROOT_NAME; 086 } 087 088 /** 089 * Returns type of the node. 090 * 091 * @return node kind 092 */ 093 @Override 094 public int getNodeKind() { 095 return Type.DOCUMENT; 096 } 097 098 /** 099 * Returns parent. 100 * 101 * @return parent 102 */ 103 @Override 104 public NodeInfo getParent() { 105 return null; 106 } 107 108 /** 109 * Returns root of the tree. 110 * 111 * @return root of the tree 112 */ 113 @Override 114 public NodeInfo getRoot() { 115 return this; 116 } 117 118 /** 119 * Returns ancestor axis iterator. Root has no ancestors. 120 * 121 * @param predicate filter for the iterator, may be null 122 * @return empty iterator 123 */ 124 @Override 125 public SequenceIterator iterateAncestorAxis(NodePredicate predicate) { 126 return createEmptyIterator(); 127 } 128 129 /** 130 * Returns parent axis iterator. Root has no parent. 131 * 132 * @param predicate filter for the iterator, may be null 133 * @return empty iterator 134 */ 135 @Override 136 public SequenceIterator iterateParentAxis(NodePredicate predicate) { 137 return createEmptyIterator(); 138 } 139 140 /** 141 * Returns following axis iterator. Root has no following nodes. 142 * 143 * @param predicate filter for the iterator, may be null 144 * @return empty iterator 145 */ 146 @Override 147 public SequenceIterator iterateFollowingAxis(NodePredicate predicate) { 148 return createEmptyIterator(); 149 } 150 151 /** 152 * Returns following-sibling axis iterator. Root has no siblings. 153 * 154 * @param predicate filter for the iterator, may be null 155 * @return empty iterator 156 */ 157 @Override 158 public SequenceIterator iterateFollowingSiblingAxis(NodePredicate predicate) { 159 return createEmptyIterator(); 160 } 161 162 /** 163 * Returns preceding axis iterator. Root has no preceding nodes. 164 * 165 * @param predicate filter for the iterator, may be null 166 * @return empty iterator 167 */ 168 @Override 169 public SequenceIterator iteratePrecedingAxis(NodePredicate predicate) { 170 return createEmptyIterator(); 171 } 172 173 /** 174 * Returns preceding-sibling axis iterator. Root has no siblings. 175 * 176 * @param predicate filter for the iterator, may be null 177 * @return empty iterator 178 */ 179 @Override 180 public SequenceIterator iteratePrecedingSiblingAxis(NodePredicate predicate) { 181 return createEmptyIterator(); 182 } 183 184 /** 185 * Returns ancestor-or-self axis iterator. 186 * 187 * @param predicate filter for the iterator, may be null 188 * @return iterator over the current node 189 */ 190 @Override 191 public SequenceIterator iterateAncestorOrSelfAxis(NodePredicate predicate) { 192 return filter(SingletonIterator.makeIterator(this), predicate); 193 } 194 195 /** 196 * Returns self axis iterator. 197 * 198 * @param predicate filter for the iterator, may be null 199 * @return iterator over the current node 200 */ 201 @Override 202 public SequenceIterator iterateSelfAxis(NodePredicate predicate) { 203 return filter(SingletonIterator.makeIterator(this), predicate); 204 } 205 206 /** 207 * Returns child axis iterator. 208 * 209 * @param predicate filter for the iterator, may be null 210 * @return iterator over the children 211 */ 212 @Override 213 public SequenceIterator iterateChildAxis(NodePredicate predicate) { 214 final SequenceIterator result; 215 if (hasChildNodes()) { 216 result = filter(new ArrayIterator.OfNodes<>( 217 getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY)), predicate); 218 } 219 else { 220 result = createEmptyIterator(); 221 } 222 return result; 223 } 224 225 /** 226 * Returns descendant axis iterator. 227 * 228 * @param predicate filter for the iterator, may be null 229 * @return iterator over the descendants 230 */ 231 @Override 232 public SequenceIterator iterateDescendantAxis(NodePredicate predicate) { 233 final SequenceIterator result; 234 if (hasChildNodes()) { 235 result = filter( 236 new DescendantIterator(this, DescendantIterator.StartWith.CHILDREN), predicate); 237 } 238 else { 239 result = createEmptyIterator(); 240 } 241 return result; 242 } 243 244 /** 245 * Returns descendant-or-self axis iterator. 246 * 247 * @param predicate filter for the iterator, may be null 248 * @return iterator over the current node and its descendants 249 */ 250 @Override 251 public SequenceIterator iterateDescendantOrSelfAxis(NodePredicate predicate) { 252 return filter( 253 new DescendantIterator(this, DescendantIterator.StartWith.CURRENT_NODE), predicate); 254 } 255 256 /** 257 * Attribute axis is not supported for the root node. 258 * 259 * @param predicate filter for the iterator, may be null 260 * @return never 261 */ 262 @Override 263 public SequenceIterator iterateAttributeAxis(NodePredicate predicate) { 264 throw throwUnsupportedOperationException(); 265 } 266 267 /** 268 * Namespace axis is not supported for the root node. 269 * 270 * @param predicate filter for the iterator, may be null 271 * @return never 272 */ 273 @Override 274 public SequenceIterator iterateNamespaceAxis(NodePredicate predicate) { 275 throw throwUnsupportedOperationException(); 276 } 277 278 /** 279 * Getter method for node depth. 280 * 281 * @return always {@code 0} 282 */ 283 @Override 284 public int getDepth() { 285 return 0; 286 } 287 288 /** 289 * Creates an iterator without items. 290 * 291 * @return the shared empty iterator 292 */ 293 private static SequenceIterator createEmptyIterator() { 294 return EmptyIterator.getInstance(); 295 } 296 297 /** 298 * Returns UnsupportedOperationException exception. 299 * 300 * @return UnsupportedOperationException exception 301 */ 302 private static UnsupportedOperationException throwUnsupportedOperationException() { 303 return new UnsupportedOperationException("Operation is not supported"); 304 } 305 306}