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}