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-2017 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  
     /** String literal for text attribute. */
 41  
     private static final String TEXT_ATTRIBUTE_NAME = "text";
 42  
 
 43  
     /** The root node. */
 44  
     private final AbstractNode root;
 45  
 
 46  
     /** The parent of the current node. */
 47  
     private final AbstractNode parent;
 48  
 
 49  
     /** The ast node. */
 50  
     private final DetailAST detailAst;
 51  
 
 52  
     /** Represents text of the DetailAST. */
 53  
     private final String text;
 54  
 
 55  
     /** The attributes. */
 56  
     private AbstractNode[] attributes;
 57  
 
 58  
     /** Represents value of TokenTypes#IDENT. */
 59  
     private String ident;
 60  
 
 61  
     /**
 62  
      * Creates a new {@code ElementNode} instance.
 63  
      *
 64  
      * @param root {@code Node} root of the tree
 65  
      * @param parent {@code Node} parent of the current node
 66  
      * @param detailAst reference to {@code DetailAST}
 67  
      */
 68  6336
     public ElementNode(AbstractNode root, AbstractNode parent, DetailAST detailAst) {
 69  6336
         this.parent = parent;
 70  6336
         this.root = root;
 71  6336
         this.detailAst = detailAst;
 72  6336
         setIdent();
 73  6336
         createChildren();
 74  6336
         text = TokenUtils.getTokenName(detailAst.getType());
 75  6336
     }
 76  
 
 77  
     /**
 78  
      * Iterates children of the current node and
 79  
      * recursively creates new Xpath-nodes.
 80  
      */
 81  
     private void createChildren() {
 82  6336
         DetailAST currentChild = detailAst.getFirstChild();
 83  13982
         while (currentChild != null) {
 84  7646
             if (currentChild.getType() != TokenTypes.IDENT) {
 85  6174
                 final ElementNode child = new ElementNode(root, this, currentChild);
 86  6174
                 addChild(child);
 87  
             }
 88  7646
             currentChild = currentChild.getNextSibling();
 89  
         }
 90  6336
     }
 91  
 
 92  
     /**
 93  
      * Returns attribute value. Throws {@code UnsupportedOperationException} in case,
 94  
      * when name of the attribute is not equal to 'text'.
 95  
      * @param namespace namespace
 96  
      * @param localPart actual name of the attribute
 97  
      * @return attribute value
 98  
      */
 99  
     @Override
 100  
     public String getAttributeValue(String namespace, String localPart) {
 101  87
         if (TEXT_ATTRIBUTE_NAME.equals(localPart)) {
 102  86
             return ident;
 103  
         }
 104  
         else {
 105  1
             throw throwUnsupportedOperationException();
 106  
         }
 107  
     }
 108  
 
 109  
     /**
 110  
      * Returns local part.
 111  
      * @return local part
 112  
      */
 113  
     // -@cs[SimpleAccessorNameNotation] Overrides method from the base class.
 114  
     // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166
 115  
     @Override
 116  
     public String getLocalPart() {
 117  2494
         return text;
 118  
     }
 119  
 
 120  
     /**
 121  
      * Returns type of the node.
 122  
      * @return node kind
 123  
      */
 124  
     @Override
 125  
     public int getNodeKind() {
 126  2694
         return Type.ELEMENT;
 127  
     }
 128  
 
 129  
     /**
 130  
      * Returns parent.
 131  
      * @return parent
 132  
      */
 133  
     @Override
 134  
     public NodeInfo getParent() {
 135  11
         return parent;
 136  
     }
 137  
 
 138  
     /**
 139  
      * Returns root.
 140  
      * @return root
 141  
      */
 142  
     @Override
 143  
     public NodeInfo getRoot() {
 144  1
         return root;
 145  
     }
 146  
 
 147  
     /**
 148  
      * Returns string value.
 149  
      * @return string value
 150  
      */
 151  
     // -@cs[SimpleAccessorNameNotation] Overrides method from the base class.
 152  
     // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166
 153  
     @Override
 154  
     public String getStringValue() {
 155  1
         return text;
 156  
     }
 157  
 
 158  
     /**
 159  
      * Determines axis iteration algorithm. Throws {@code UnsupportedOperationException} in case,
 160  
      * when there is no axis iterator for given axisNumber.
 161  
      *
 162  
      * @param axisNumber element from {@code AxisInfo}
 163  
      * @return {@code AxisIterator} object
 164  
      */
 165  
     @Override
 166  
     public AxisIterator iterateAxis(byte axisNumber) {
 167  
         final AxisIterator result;
 168  1248
         switch (axisNumber) {
 169  
             case AxisInfo.ANCESTOR:
 170  1
                 result = new Navigator.AncestorEnumeration(this, false);
 171  1
                 break;
 172  
             case AxisInfo.ANCESTOR_OR_SELF:
 173  1
                 result = new Navigator.AncestorEnumeration(this, true);
 174  1
                 break;
 175  
             case AxisInfo.ATTRIBUTE:
 176  91
                 if (attributes == null) {
 177  65
                     result = EmptyIterator.OfNodes.THE_INSTANCE;
 178  
                 }
 179  
                 else {
 180  26
                     result = new ArrayIterator.OfNodes(attributes);
 181  
                 }
 182  26
                 break;
 183  
             case AxisInfo.CHILD:
 184  1115
                 if (hasChildNodes()) {
 185  1111
                     result = new ArrayIterator.OfNodes(
 186  1111
                             getChildren().toArray(new AbstractNode[getChildren().size()]));
 187  
                 }
 188  
                 else {
 189  4
                     result = EmptyIterator.OfNodes.THE_INSTANCE;
 190  
                 }
 191  4
                 break;
 192  
             case AxisInfo.DESCENDANT:
 193  12
                 if (hasChildNodes()) {
 194  8
                     result = new Navigator.DescendantEnumeration(this, false, true);
 195  
                 }
 196  
                 else {
 197  4
                     result = EmptyIterator.OfNodes.THE_INSTANCE;
 198  
                 }
 199  4
                 break;
 200  
             case AxisInfo.DESCENDANT_OR_SELF:
 201  3
                 result = new Navigator.DescendantEnumeration(this, true, true);
 202  3
                 break;
 203  
             case AxisInfo.PARENT:
 204  23
                 result = SingleNodeIterator.makeIterator(parent);
 205  23
                 break;
 206  
             case AxisInfo.SELF:
 207  1
                 result = SingleNodeIterator.makeIterator(this);
 208  1
                 break;
 209  
             default:
 210  1
                 throw throwUnsupportedOperationException();
 211  
         }
 212  1247
         return result;
 213  
     }
 214  
 
 215  
     /**
 216  
      * Returns line number.
 217  
      * @return line number
 218  
      */
 219  
     @Override
 220  
     public int getLineNumber() {
 221  11
         return detailAst.getLineNo();
 222  
     }
 223  
 
 224  
     /**
 225  
      * Returns column number.
 226  
      * @return column number
 227  
      */
 228  
     @Override
 229  
     public int getColumnNumber() {
 230  7
         return detailAst.getColumnNo();
 231  
     }
 232  
 
 233  
     /**
 234  
      * Getter method for token type.
 235  
      * @return token type
 236  
      */
 237  
     @Override
 238  
     public int getTokenType() {
 239  12
         return detailAst.getType();
 240  
     }
 241  
 
 242  
     /**
 243  
      * Returns underlying node.
 244  
      * @return underlying node
 245  
      */
 246  
     // -@cs[SimpleAccessorNameNotation] Overrides method from the base class.
 247  
     // Issue: https://github.com/sevntu-checkstyle/sevntu.checkstyle/issues/166
 248  
     @Override
 249  
     public DetailAST getUnderlyingNode() {
 250  27
         return detailAst;
 251  
     }
 252  
 
 253  
     /**
 254  
      * Finds child element with {@link TokenTypes#IDENT}, extracts its value and stores it.
 255  
      * Value can be accessed using {@code @text} attribute. Now {@code @text} attribute is only
 256  
      * supported attribute.
 257  
      */
 258  
     private void setIdent() {
 259  6336
         final DetailAST identAst = detailAst.findFirstToken(TokenTypes.IDENT);
 260  6336
         if (identAst != null) {
 261  1382
             ident = identAst.getText();
 262  1382
             attributes = new AbstractNode[1];
 263  1382
             attributes[0] = new AttributeNode(TEXT_ATTRIBUTE_NAME, ident);
 264  
         }
 265  6336
     }
 266  
 
 267  
     /**
 268  
      * Returns UnsupportedOperationException exception.
 269  
      * @return UnsupportedOperationException exception
 270  
      */
 271  
     private static UnsupportedOperationException throwUnsupportedOperationException() {
 272  2
         return new UnsupportedOperationException("Operation is not supported");
 273  
     }
 274  
 }