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