001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2019 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.api.DetailAST; 023import com.puppycrawl.tools.checkstyle.api.TokenTypes; 024import net.sf.saxon.Configuration; 025import net.sf.saxon.om.AxisInfo; 026import net.sf.saxon.om.GenericTreeInfo; 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.tree.util.Navigator; 033import net.sf.saxon.type.Type; 034 035/** 036 * Represents root node of Xpath-tree. 037 * 038 */ 039public class RootNode extends AbstractNode { 040 041 /** Name of the root element. */ 042 private static final String ROOT_NAME = "ROOT"; 043 044 /** Constant for optimization. */ 045 private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0]; 046 047 /** The ast node. */ 048 private final DetailAST detailAst; 049 050 /** 051 * Creates a new {@code RootNode} instance. 052 * 053 * @param detailAst reference to {@code DetailAST} 054 */ 055 public RootNode(DetailAST detailAst) { 056 super(new GenericTreeInfo(Configuration.newConfiguration())); 057 this.detailAst = detailAst; 058 059 if (detailAst != null) { 060 createChildren(); 061 } 062 } 063 064 /** 065 * Iterates siblings of the current node and 066 * recursively creates new Xpath-nodes. 067 */ 068 private void createChildren() { 069 DetailAST currentChild = detailAst; 070 while (currentChild != null) { 071 final ElementNode child = new ElementNode(this, this, currentChild); 072 addChild(child); 073 currentChild = currentChild.getNextSibling(); 074 } 075 } 076 077 /** 078 * Returns attribute value. Throws {@code UnsupportedOperationException} because root node 079 * has no attributes. 080 * @param namespace namespace 081 * @param localPart actual name of the attribute 082 * @return attribute value 083 */ 084 @Override 085 public String getAttributeValue(String namespace, String localPart) { 086 throw throwUnsupportedOperationException(); 087 } 088 089 /** 090 * Returns local part. 091 * @return local part 092 */ 093 // -@cs[SimpleAccessorNameNotation] Overrides method from the base class. 094 // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166 095 @Override 096 public String getLocalPart() { 097 return ROOT_NAME; 098 } 099 100 /** 101 * Returns type of the node. 102 * @return node kind 103 */ 104 @Override 105 public int getNodeKind() { 106 return Type.DOCUMENT; 107 } 108 109 /** 110 * Returns parent. 111 * @return parent 112 */ 113 @Override 114 public NodeInfo getParent() { 115 return null; 116 } 117 118 /** 119 * Returns root of the tree. 120 * @return root of the tree 121 */ 122 @Override 123 public NodeInfo getRoot() { 124 return this; 125 } 126 127 /** 128 * Returns string value. 129 * @return string value 130 */ 131 // -@cs[SimpleAccessorNameNotation] Overrides method from the base class. 132 // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166 133 @Override 134 public String getStringValue() { 135 return ROOT_NAME; 136 } 137 138 /** 139 * Determines axis iteration algorithm. Throws {@code UnsupportedOperationException} in case, 140 * when there is no axis iterator for given axisNumber. 141 * @param axisNumber element from {@code AxisInfo} 142 * @return {@code AxisIterator} object 143 */ 144 @Override 145 public AxisIterator iterateAxis(byte axisNumber) { 146 final AxisIterator result; 147 switch (axisNumber) { 148 case AxisInfo.ANCESTOR: 149 case AxisInfo.ATTRIBUTE: 150 case AxisInfo.PARENT: 151 result = EmptyIterator.OfNodes.THE_INSTANCE; 152 break; 153 case AxisInfo.ANCESTOR_OR_SELF: 154 case AxisInfo.SELF: 155 try (AxisIterator iterator = SingleNodeIterator.makeIterator(this)) { 156 result = iterator; 157 } 158 break; 159 case AxisInfo.CHILD: 160 if (hasChildNodes()) { 161 try (AxisIterator iterator = new ArrayIterator.OfNodes( 162 getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY))) { 163 result = iterator; 164 } 165 } 166 else { 167 result = EmptyIterator.OfNodes.THE_INSTANCE; 168 } 169 break; 170 case AxisInfo.DESCENDANT: 171 if (hasChildNodes()) { 172 try (AxisIterator iterator = 173 new Navigator.DescendantEnumeration(this, false, true)) { 174 result = iterator; 175 } 176 } 177 else { 178 result = EmptyIterator.OfNodes.THE_INSTANCE; 179 } 180 break; 181 case AxisInfo.DESCENDANT_OR_SELF: 182 try (AxisIterator iterator = 183 new Navigator.DescendantEnumeration(this, true, true)) { 184 result = iterator; 185 } 186 break; 187 default: 188 throw throwUnsupportedOperationException(); 189 } 190 return result; 191 } 192 193 /** 194 * Returns line number. 195 * @return line number 196 */ 197 @Override 198 public int getLineNumber() { 199 return detailAst.getLineNo(); 200 } 201 202 /** 203 * Returns column number. 204 * @return column number 205 */ 206 @Override 207 public int getColumnNumber() { 208 return detailAst.getColumnNo(); 209 } 210 211 /** 212 * Getter method for token type. 213 * @return token type 214 */ 215 @Override 216 public int getTokenType() { 217 return TokenTypes.EOF; 218 } 219 220 /** 221 * Returns underlying node. 222 * @return underlying node 223 */ 224 // -@cs[SimpleAccessorNameNotation] Overrides method from the base class. 225 // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166 226 @Override 227 public DetailAST getUnderlyingNode() { 228 return detailAst; 229 } 230 231 /** 232 * Returns UnsupportedOperationException exception. 233 * @return UnsupportedOperationException exception 234 */ 235 private static UnsupportedOperationException throwUnsupportedOperationException() { 236 return new UnsupportedOperationException("Operation is not supported"); 237 } 238 239}