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}