001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2023 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.AxisInfo; 025import net.sf.saxon.om.GenericTreeInfo; 026import net.sf.saxon.om.NamespaceUri; 027import net.sf.saxon.om.NodeInfo; 028import net.sf.saxon.tree.iter.ArrayIterator; 029import net.sf.saxon.tree.iter.AxisIterator; 030import net.sf.saxon.tree.iter.EmptyIterator; 031import net.sf.saxon.tree.iter.SingleNodeIterator; 032import net.sf.saxon.type.Type; 033 034/** 035 * Represents root node of Xpath-tree. 036 */ 037public abstract class AbstractRootNode extends AbstractNode { 038 039 /** Name of the root element. */ 040 private static final String ROOT_NAME = "ROOT"; 041 042 /** Constant for optimization. */ 043 private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0]; 044 045 /** 046 * Creates a new {@code AbstractRootNode} instance. 047 */ 048 protected AbstractRootNode() { 049 super(new GenericTreeInfo(Configuration.newConfiguration())); 050 } 051 052 /** 053 * Compares current object with specified for order. 054 * Throws {@code UnsupportedOperationException} because functionality not required here. 055 * 056 * @param nodeInfo another {@code NodeInfo} object 057 * @return number representing order of current object to specified one 058 */ 059 @Override 060 public int compareOrder(NodeInfo nodeInfo) { 061 throw throwUnsupportedOperationException(); 062 } 063 064 /** 065 * Returns attribute value. Throws {@code UnsupportedOperationException} because root node 066 * has no attributes. 067 * 068 * @param namespace namespace 069 * @param localPart actual name of the attribute 070 * @return attribute value 071 */ 072 @Override 073 public String getAttributeValue(NamespaceUri namespace, String localPart) { 074 throw throwUnsupportedOperationException(); 075 } 076 077 /** 078 * Returns local part. 079 * 080 * @return local part 081 */ 082 @Override 083 public String getLocalPart() { 084 return ROOT_NAME; 085 } 086 087 /** 088 * Returns type of the node. 089 * 090 * @return node kind 091 */ 092 @Override 093 public int getNodeKind() { 094 return Type.DOCUMENT; 095 } 096 097 /** 098 * Returns parent. 099 * 100 * @return parent 101 */ 102 @Override 103 public NodeInfo getParent() { 104 return null; 105 } 106 107 /** 108 * Returns root of the tree. 109 * 110 * @return root of the tree 111 */ 112 @Override 113 public NodeInfo getRoot() { 114 return this; 115 } 116 117 /** 118 * Determines axis iteration algorithm. Throws {@code UnsupportedOperationException} in case, 119 * when there is no axis iterator for given axisNumber. 120 * 121 * @param axisNumber element from {@code AxisInfo} 122 * @return {@code AxisIterator} object 123 */ 124 @Override 125 public AxisIterator iterateAxis(int axisNumber) { 126 final AxisIterator result; 127 switch (axisNumber) { 128 case AxisInfo.ANCESTOR: 129 case AxisInfo.ATTRIBUTE: 130 case AxisInfo.PARENT: 131 case AxisInfo.FOLLOWING: 132 case AxisInfo.FOLLOWING_SIBLING: 133 case AxisInfo.PRECEDING: 134 case AxisInfo.PRECEDING_SIBLING: 135 result = EmptyIterator.ofNodes(); 136 break; 137 case AxisInfo.ANCESTOR_OR_SELF: 138 case AxisInfo.SELF: 139 result = SingleNodeIterator.makeIterator(this); 140 break; 141 case AxisInfo.CHILD: 142 if (hasChildNodes()) { 143 result = new ArrayIterator.OfNodes<>( 144 getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY)); 145 } 146 else { 147 result = EmptyIterator.ofNodes(); 148 } 149 break; 150 case AxisInfo.DESCENDANT: 151 if (hasChildNodes()) { 152 result = new DescendantIterator(this, DescendantIterator.StartWith.CHILDREN); 153 } 154 else { 155 result = EmptyIterator.ofNodes(); 156 } 157 break; 158 case AxisInfo.DESCENDANT_OR_SELF: 159 result = new DescendantIterator(this, DescendantIterator.StartWith.CURRENT_NODE); 160 break; 161 default: 162 throw throwUnsupportedOperationException(); 163 } 164 return result; 165 } 166 167 /** 168 * Getter method for node depth. 169 * 170 * @return always {@code 0} 171 */ 172 @Override 173 public int getDepth() { 174 return 0; 175 } 176 177 /** 178 * Returns UnsupportedOperationException exception. 179 * 180 * @return UnsupportedOperationException exception 181 */ 182 private static UnsupportedOperationException throwUnsupportedOperationException() { 183 return new UnsupportedOperationException("Operation is not supported"); 184 } 185 186}