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