Coverage Report - com.puppycrawl.tools.checkstyle.xpath.ElementNode
 
Classes in this File Line Coverage Branch Coverage Complexity
ElementNode
100%
60/60
100%
23/23
2.2
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2018 the original author or authors.
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 
 20  
 package com.puppycrawl.tools.checkstyle.xpath;
 21  
 
 22  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 23  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 24  
 import com.puppycrawl.tools.checkstyle.utils.TokenUtils;
 25  
 import net.sf.saxon.om.AxisInfo;
 26  
 import net.sf.saxon.om.NodeInfo;
 27  
 import net.sf.saxon.tree.iter.ArrayIterator;
 28  
 import net.sf.saxon.tree.iter.AxisIterator;
 29  
 import net.sf.saxon.tree.iter.EmptyIterator;
 30  
 import net.sf.saxon.tree.iter.SingleNodeIterator;
 31  
 import net.sf.saxon.tree.util.Navigator;
 32  
 import net.sf.saxon.type.Type;
 33  
 
 34  
 /**
 35  
  * Represents element node of Xpath-tree.
 36  
  *
 37  
  * @author Timur Tibeyev
 38  
  */
 39  
 public class ElementNode extends AbstractNode {
 40  
 
 41  
     /** String literal for text attribute. */
 42  
     private static final String TEXT_ATTRIBUTE_NAME = "text";
 43  
 
 44  
     /** The root node. */
 45  
     private final AbstractNode root;
 46  
 
 47  
     /** The parent of the current node. */
 48  
     private final AbstractNode parent;
 49  
 
 50  
     /** The ast node. */
 51  
     private final DetailAST detailAst;
 52  
 
 53  
     /** Represents text of the DetailAST. */
 54  
     private final String text;
 55  
 
 56  
     /** The attributes. */
 57  
     private AbstractNode[] attributes;
 58  
 
 59  
     /** Represents value of TokenTypes#IDENT. */
 60  
     private String ident;
 61  
 
 62  
     /**
 63  
      * Creates a new {@code ElementNode} instance.
 64  
      *
 65  
      * @param root {@code Node} root of the tree
 66  
      * @param parent {@code Node} parent of the current node
 67  
      * @param detailAst reference to {@code DetailAST}
 68  
      */
 69  5958
     public ElementNode(AbstractNode root, AbstractNode parent, DetailAST detailAst) {
 70  5958
         this.parent = parent;
 71  5958
         this.root = root;
 72  5958
         this.detailAst = detailAst;
 73  5958
         setIdent();
 74  5958
         createChildren();
 75  5958
         text = TokenUtils.getTokenName(detailAst.getType());
 76  5958
     }
 77  
 
 78  
     /**
 79  
      * Iterates children of the current node and
 80  
      * recursively creates new Xpath-nodes.
 81  
      */
 82  
     private void createChildren() {
 83  5958
         DetailAST currentChild = detailAst.getFirstChild();
 84  13226
         while (currentChild != null) {
 85  7268
             if (currentChild.getType() != TokenTypes.IDENT) {
 86  5796
                 final ElementNode child = new ElementNode(root, this, currentChild);
 87  5796
                 addChild(child);
 88  
             }
 89  7268
             currentChild = currentChild.getNextSibling();
 90  
         }
 91  5958
     }
 92  
 
 93  
     /**
 94  
      * Returns attribute value. Throws {@code UnsupportedOperationException} in case,
 95  
      * when name of the attribute is not equal to 'text'.
 96  
      * @param namespace namespace
 97  
      * @param localPart actual name of the attribute
 98  
      * @return attribute value
 99  
      */
 100  
     @Override
 101  
     public String getAttributeValue(String namespace, String localPart) {
 102  87
         if (TEXT_ATTRIBUTE_NAME.equals(localPart)) {
 103  86
             return ident;
 104  
         }
 105  
         else {
 106  1
             throw throwUnsupportedOperationException();
 107  
         }
 108  
     }
 109  
 
 110  
     /**
 111  
      * Returns local part.
 112  
      * @return local part
 113  
      */
 114  
     // -@cs[SimpleAccessorNameNotation] Overrides method from the base class.
 115  
     // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166
 116  
     @Override
 117  
     public String getLocalPart() {
 118  2347
         return text;
 119  
     }
 120  
 
 121  
     /**
 122  
      * Returns type of the node.
 123  
      * @return node kind
 124  
      */
 125  
     @Override
 126  
     public int getNodeKind() {
 127  2541
         return Type.ELEMENT;
 128  
     }
 129  
 
 130  
     /**
 131  
      * Returns parent.
 132  
      * @return parent
 133  
      */
 134  
     @Override
 135  
     public NodeInfo getParent() {
 136  11
         return parent;
 137  
     }
 138  
 
 139  
     /**
 140  
      * Returns root.
 141  
      * @return root
 142  
      */
 143  
     @Override
 144  
     public NodeInfo getRoot() {
 145  1
         return root;
 146  
     }
 147  
 
 148  
     /**
 149  
      * Returns string value.
 150  
      * @return string value
 151  
      */
 152  
     // -@cs[SimpleAccessorNameNotation] Overrides method from the base class.
 153  
     // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166
 154  
     @Override
 155  
     public String getStringValue() {
 156  1
         return text;
 157  
     }
 158  
 
 159  
     /**
 160  
      * Determines axis iteration algorithm. Throws {@code UnsupportedOperationException} in case,
 161  
      * when there is no axis iterator for given axisNumber.
 162  
      *
 163  
      * @param axisNumber element from {@code AxisInfo}
 164  
      * @return {@code AxisIterator} object
 165  
      */
 166  
     @Override
 167  
     public AxisIterator iterateAxis(byte axisNumber) {
 168  
         final AxisIterator result;
 169  1193
         switch (axisNumber) {
 170  
             case AxisInfo.ANCESTOR:
 171  1
                 result = new Navigator.AncestorEnumeration(this, false);
 172  1
                 break;
 173  
             case AxisInfo.ANCESTOR_OR_SELF:
 174  1
                 result = new Navigator.AncestorEnumeration(this, true);
 175  1
                 break;
 176  
             case AxisInfo.ATTRIBUTE:
 177  85
                 if (attributes == null) {
 178  59
                     result = EmptyIterator.OfNodes.THE_INSTANCE;
 179  
                 }
 180  
                 else {
 181  26
                     result = new ArrayIterator.OfNodes(attributes);
 182  
                 }
 183  26
                 break;
 184  
             case AxisInfo.CHILD:
 185  1066
                 if (hasChildNodes()) {
 186  1062
                     result = new ArrayIterator.OfNodes(
 187  1062
                             getChildren().toArray(new AbstractNode[getChildren().size()]));
 188  
                 }
 189  
                 else {
 190  4
                     result = EmptyIterator.OfNodes.THE_INSTANCE;
 191  
                 }
 192  4
                 break;
 193  
             case AxisInfo.DESCENDANT:
 194  12
                 if (hasChildNodes()) {
 195  8
                     result = new Navigator.DescendantEnumeration(this, false, true);
 196  
                 }
 197  
                 else {
 198  4
                     result = EmptyIterator.OfNodes.THE_INSTANCE;
 199  
                 }
 200  4
                 break;
 201  
             case AxisInfo.DESCENDANT_OR_SELF:
 202  3
                 result = new Navigator.DescendantEnumeration(this, true, true);
 203  3
                 break;
 204  
             case AxisInfo.PARENT:
 205  23
                 result = SingleNodeIterator.makeIterator(parent);
 206  23
                 break;
 207  
             case AxisInfo.SELF:
 208  1
                 result = SingleNodeIterator.makeIterator(this);
 209  1
                 break;
 210  
             default:
 211  1
                 throw throwUnsupportedOperationException();
 212  
         }
 213  1192
         return result;
 214  
     }
 215  
 
 216  
     /**
 217  
      * Returns line number.
 218  
      * @return line number
 219  
      */
 220  
     @Override
 221  
     public int getLineNumber() {
 222  11
         return detailAst.getLineNo();
 223  
     }
 224  
 
 225  
     /**
 226  
      * Returns column number.
 227  
      * @return column number
 228  
      */
 229  
     @Override
 230  
     public int getColumnNumber() {
 231  7
         return detailAst.getColumnNo();
 232  
     }
 233  
 
 234  
     /**
 235  
      * Getter method for token type.
 236  
      * @return token type
 237  
      */
 238  
     @Override
 239  
     public int getTokenType() {
 240  12
         return detailAst.getType();
 241  
     }
 242  
 
 243  
     /**
 244  
      * Returns underlying node.
 245  
      * @return underlying node
 246  
      */
 247  
     // -@cs[SimpleAccessorNameNotation] Overrides method from the base class.
 248  
     // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166
 249  
     @Override
 250  
     public DetailAST getUnderlyingNode() {
 251  27
         return detailAst;
 252  
     }
 253  
 
 254  
     /**
 255  
      * Finds child element with {@link TokenTypes#IDENT}, extracts its value and stores it.
 256  
      * Value can be accessed using {@code @text} attribute. Now {@code @text} attribute is only
 257  
      * supported attribute.
 258  
      */
 259  
     private void setIdent() {
 260  5958
         final DetailAST identAst = detailAst.findFirstToken(TokenTypes.IDENT);
 261  5958
         if (identAst != null) {
 262  1382
             ident = identAst.getText();
 263  1382
             attributes = new AbstractNode[1];
 264  1382
             attributes[0] = new AttributeNode(TEXT_ATTRIBUTE_NAME, ident);
 265  
         }
 266  5958
     }
 267  
 
 268  
     /**
 269  
      * Returns UnsupportedOperationException exception.
 270  
      * @return UnsupportedOperationException exception
 271  
      */
 272  
     private static UnsupportedOperationException throwUnsupportedOperationException() {
 273  2
         return new UnsupportedOperationException("Operation is not supported");
 274  
     }
 275  
 
 276  
 }