001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2022 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 java.util.List;
023
024import com.puppycrawl.tools.checkstyle.api.DetailAST;
025import com.puppycrawl.tools.checkstyle.api.TokenTypes;
026import com.puppycrawl.tools.checkstyle.utils.XpathUtil;
027import com.puppycrawl.tools.checkstyle.xpath.iterators.DescendantIterator;
028import net.sf.saxon.Configuration;
029import net.sf.saxon.om.AxisInfo;
030import net.sf.saxon.om.GenericTreeInfo;
031import net.sf.saxon.om.NodeInfo;
032import net.sf.saxon.tree.iter.ArrayIterator;
033import net.sf.saxon.tree.iter.AxisIterator;
034import net.sf.saxon.tree.iter.EmptyIterator;
035import net.sf.saxon.tree.iter.SingleNodeIterator;
036import net.sf.saxon.type.Type;
037
038/**
039 * Represents root node of Xpath-tree.
040 *
041 */
042public class RootNode extends AbstractNode {
043
044    /** Name of the root element. */
045    private static final String ROOT_NAME = "ROOT";
046
047    /** Constant for optimization. */
048    private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0];
049
050    /** The ast node. */
051    private final DetailAST detailAst;
052
053    /**
054     * Creates a new {@code RootNode} instance.
055     *
056     * @param detailAst reference to {@code DetailAST}
057     */
058    public RootNode(DetailAST detailAst) {
059        super(new GenericTreeInfo(Configuration.newConfiguration()));
060        this.detailAst = detailAst;
061    }
062
063    /**
064     * Compares current object with specified for order.
065     * Throws {@code UnsupportedOperationException} because functionality not required here.
066     *
067     * @param nodeInfo another {@code NodeInfo} object
068     * @return number representing order of current object to specified one
069     */
070    @Override
071    public int compareOrder(NodeInfo nodeInfo) {
072        throw throwUnsupportedOperationException();
073    }
074
075    /**
076     * Iterates siblings of the current node and
077     * recursively creates new Xpath-nodes.
078     *
079     * @return children list
080     */
081    @Override
082    protected List<AbstractNode> createChildren() {
083        return XpathUtil.createChildren(this, this, detailAst);
084    }
085
086    /**
087     * Determine whether the node has any children.
088     *
089     * @return {@code true} is the node has any children.
090     */
091    @Override
092    public boolean hasChildNodes() {
093        return detailAst != null;
094    }
095
096    /**
097     * Returns attribute value. Throws {@code UnsupportedOperationException} because root node
098     * has no attributes.
099     *
100     * @param namespace namespace
101     * @param localPart actual name of the attribute
102     * @return attribute value
103     */
104    @Override
105    public String getAttributeValue(String namespace, String localPart) {
106        throw throwUnsupportedOperationException();
107    }
108
109    /**
110     * Returns local part.
111     *
112     * @return local part
113     */
114    @Override
115    public String getLocalPart() {
116        return ROOT_NAME;
117    }
118
119    /**
120     * Returns type of the node.
121     *
122     * @return node kind
123     */
124    @Override
125    public int getNodeKind() {
126        return Type.DOCUMENT;
127    }
128
129    /**
130     * Returns parent.
131     *
132     * @return parent
133     */
134    @Override
135    public NodeInfo getParent() {
136        return null;
137    }
138
139    /**
140     * Returns root of the tree.
141     *
142     * @return root of the tree
143     */
144    @Override
145    public NodeInfo getRoot() {
146        return this;
147    }
148
149    /**
150     * Determines axis iteration algorithm. Throws {@code UnsupportedOperationException} in case,
151     * when there is no axis iterator for given axisNumber.
152     *
153     * @param axisNumber element from {@code AxisInfo}
154     * @return {@code AxisIterator} object
155     * @noinspection resource, IOResourceOpenedButNotSafelyClosed
156     */
157    @Override
158    public AxisIterator iterateAxis(int axisNumber) {
159        final AxisIterator result;
160        switch (axisNumber) {
161            case AxisInfo.ANCESTOR:
162            case AxisInfo.ATTRIBUTE:
163            case AxisInfo.PARENT:
164            case AxisInfo.FOLLOWING:
165            case AxisInfo.FOLLOWING_SIBLING:
166            case AxisInfo.PRECEDING:
167            case AxisInfo.PRECEDING_SIBLING:
168                result = EmptyIterator.ofNodes();
169                break;
170            case AxisInfo.ANCESTOR_OR_SELF:
171            case AxisInfo.SELF:
172                result = SingleNodeIterator.makeIterator(this);
173                break;
174            case AxisInfo.CHILD:
175                if (hasChildNodes()) {
176                    result = new ArrayIterator.OfNodes(
177                            getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY));
178                }
179                else {
180                    result = EmptyIterator.ofNodes();
181                }
182                break;
183            case AxisInfo.DESCENDANT:
184                if (hasChildNodes()) {
185                    result = new DescendantIterator(this, DescendantIterator.StartWith.CHILDREN);
186                }
187                else {
188                    result = EmptyIterator.ofNodes();
189                }
190                break;
191            case AxisInfo.DESCENDANT_OR_SELF:
192                result = new DescendantIterator(this, DescendantIterator.StartWith.CURRENT_NODE);
193                break;
194            default:
195                throw throwUnsupportedOperationException();
196        }
197        return result;
198    }
199
200    /**
201     * Returns line number.
202     *
203     * @return line number
204     */
205    @Override
206    public int getLineNumber() {
207        return detailAst.getLineNo();
208    }
209
210    /**
211     * Returns column number.
212     *
213     * @return column number
214     */
215    @Override
216    public int getColumnNumber() {
217        return detailAst.getColumnNo();
218    }
219
220    /**
221     * Getter method for token type.
222     *
223     * @return token type
224     */
225    @Override
226    public int getTokenType() {
227        return TokenTypes.COMPILATION_UNIT;
228    }
229
230    /**
231     * Returns underlying node.
232     *
233     * @return underlying node
234     */
235    @Override
236    public DetailAST getUnderlyingNode() {
237        return detailAst;
238    }
239
240    /**
241     * Getter method for node depth.
242     *
243     * @return always {@code 0}
244     */
245    @Override
246    public int getDepth() {
247        return 0;
248    }
249
250    /**
251     * Returns UnsupportedOperationException exception.
252     *
253     * @return UnsupportedOperationException exception
254     */
255    private static UnsupportedOperationException throwUnsupportedOperationException() {
256        return new UnsupportedOperationException("Operation is not supported");
257    }
258
259}