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