001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2026 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.xpath.iterators.DescendantIterator;
023import net.sf.saxon.Configuration;
024import net.sf.saxon.om.GNode;
025import net.sf.saxon.om.GenericTreeInfo;
026import net.sf.saxon.om.NamespaceUri;
027import net.sf.saxon.om.NodeInfo;
028import net.sf.saxon.om.SequenceIterator;
029import net.sf.saxon.pattern.nodetest.NodePredicate;
030import net.sf.saxon.tree.iter.ArrayIterator;
031import net.sf.saxon.tree.iter.EmptyIterator;
032import net.sf.saxon.tree.iter.SingletonIterator;
033import net.sf.saxon.type.Type;
034
035/**
036 * Represents root node of Xpath-tree.
037 */
038public abstract class AbstractRootNode extends AbstractNode {
039
040    /** Name of the root element. */
041    private static final String ROOT_NAME = "ROOT";
042
043    /** Constant for optimization. */
044    private static final AbstractNode[] EMPTY_ABSTRACT_NODE_ARRAY = new AbstractNode[0];
045
046    /**
047     * Creates a new {@code AbstractRootNode} instance.
048     */
049    protected AbstractRootNode() {
050        super(new GenericTreeInfo(Configuration.newConfiguration()));
051    }
052
053    /**
054     * Compares current object with specified for order.
055     * Throws {@code UnsupportedOperationException} because functionality not required here.
056     *
057     * @param other another {@code GNode} object
058     * @return number representing order of current object to specified one
059     */
060    @Override
061    public int compareOrder(GNode other) {
062        throw throwUnsupportedOperationException();
063    }
064
065    /**
066     * Returns attribute value. Throws {@code UnsupportedOperationException} because root node has
067     * no attributes.
068     *
069     * @param namespace namespace
070     * @param localPart actual name of the attribute
071     * @return attribute value
072     */
073    @Override
074    public String getAttributeValue(NamespaceUri namespace, String localPart) {
075        throw throwUnsupportedOperationException();
076    }
077
078    /**
079     * Returns local part.
080     *
081     * @return local part
082     */
083    @Override
084    public String getLocalPart() {
085        return ROOT_NAME;
086    }
087
088    /**
089     * Returns type of the node.
090     *
091     * @return node kind
092     */
093    @Override
094    public int getNodeKind() {
095        return Type.DOCUMENT;
096    }
097
098    /**
099     * Returns parent.
100     *
101     * @return parent
102     */
103    @Override
104    public NodeInfo getParent() {
105        return null;
106    }
107
108    /**
109     * Returns root of the tree.
110     *
111     * @return root of the tree
112     */
113    @Override
114    public NodeInfo getRoot() {
115        return this;
116    }
117
118    /**
119     * Returns ancestor axis iterator. Root has no ancestors.
120     *
121     * @param predicate filter for the iterator, may be null
122     * @return empty iterator
123     */
124    @Override
125    public SequenceIterator iterateAncestorAxis(NodePredicate predicate) {
126        return createEmptyIterator();
127    }
128
129    /**
130     * Returns parent axis iterator. Root has no parent.
131     *
132     * @param predicate filter for the iterator, may be null
133     * @return empty iterator
134     */
135    @Override
136    public SequenceIterator iterateParentAxis(NodePredicate predicate) {
137        return createEmptyIterator();
138    }
139
140    /**
141     * Returns following axis iterator. Root has no following nodes.
142     *
143     * @param predicate filter for the iterator, may be null
144     * @return empty iterator
145     */
146    @Override
147    public SequenceIterator iterateFollowingAxis(NodePredicate predicate) {
148        return createEmptyIterator();
149    }
150
151    /**
152     * Returns following-sibling axis iterator. Root has no siblings.
153     *
154     * @param predicate filter for the iterator, may be null
155     * @return empty iterator
156     */
157    @Override
158    public SequenceIterator iterateFollowingSiblingAxis(NodePredicate predicate) {
159        return createEmptyIterator();
160    }
161
162    /**
163     * Returns preceding axis iterator. Root has no preceding nodes.
164     *
165     * @param predicate filter for the iterator, may be null
166     * @return empty iterator
167     */
168    @Override
169    public SequenceIterator iteratePrecedingAxis(NodePredicate predicate) {
170        return createEmptyIterator();
171    }
172
173    /**
174     * Returns preceding-sibling axis iterator. Root has no siblings.
175     *
176     * @param predicate filter for the iterator, may be null
177     * @return empty iterator
178     */
179    @Override
180    public SequenceIterator iteratePrecedingSiblingAxis(NodePredicate predicate) {
181        return createEmptyIterator();
182    }
183
184    /**
185     * Returns ancestor-or-self axis iterator.
186     *
187     * @param predicate filter for the iterator, may be null
188     * @return iterator over the current node
189     */
190    @Override
191    public SequenceIterator iterateAncestorOrSelfAxis(NodePredicate predicate) {
192        return filter(SingletonIterator.makeIterator(this), predicate);
193    }
194
195    /**
196     * Returns self axis iterator.
197     *
198     * @param predicate filter for the iterator, may be null
199     * @return iterator over the current node
200     */
201    @Override
202    public SequenceIterator iterateSelfAxis(NodePredicate predicate) {
203        return filter(SingletonIterator.makeIterator(this), predicate);
204    }
205
206    /**
207     * Returns child axis iterator.
208     *
209     * @param predicate filter for the iterator, may be null
210     * @return iterator over the children
211     */
212    @Override
213    public SequenceIterator iterateChildAxis(NodePredicate predicate) {
214        final SequenceIterator result;
215        if (hasChildNodes()) {
216            result = filter(new ArrayIterator.OfNodes<>(
217                    getChildren().toArray(EMPTY_ABSTRACT_NODE_ARRAY)), predicate);
218        }
219        else {
220            result = createEmptyIterator();
221        }
222        return result;
223    }
224
225    /**
226     * Returns descendant axis iterator.
227     *
228     * @param predicate filter for the iterator, may be null
229     * @return iterator over the descendants
230     */
231    @Override
232    public SequenceIterator iterateDescendantAxis(NodePredicate predicate) {
233        final SequenceIterator result;
234        if (hasChildNodes()) {
235            result = filter(
236                new DescendantIterator(this, DescendantIterator.StartWith.CHILDREN), predicate);
237        }
238        else {
239            result = createEmptyIterator();
240        }
241        return result;
242    }
243
244    /**
245     * Returns descendant-or-self axis iterator.
246     *
247     * @param predicate filter for the iterator, may be null
248     * @return iterator over the current node and its descendants
249     */
250    @Override
251    public SequenceIterator iterateDescendantOrSelfAxis(NodePredicate predicate) {
252        return filter(
253            new DescendantIterator(this, DescendantIterator.StartWith.CURRENT_NODE), predicate);
254    }
255
256    /**
257     * Attribute axis is not supported for the root node.
258     *
259     * @param predicate filter for the iterator, may be null
260     * @return never
261     */
262    @Override
263    public SequenceIterator iterateAttributeAxis(NodePredicate predicate) {
264        throw throwUnsupportedOperationException();
265    }
266
267    /**
268     * Namespace axis is not supported for the root node.
269     *
270     * @param predicate filter for the iterator, may be null
271     * @return never
272     */
273    @Override
274    public SequenceIterator iterateNamespaceAxis(NodePredicate predicate) {
275        throw throwUnsupportedOperationException();
276    }
277
278    /**
279     * Getter method for node depth.
280     *
281     * @return always {@code 0}
282     */
283    @Override
284    public int getDepth() {
285        return 0;
286    }
287
288    /**
289     * Creates an iterator without items.
290     *
291     * @return the shared empty iterator
292     */
293    private static SequenceIterator createEmptyIterator() {
294        return EmptyIterator.getInstance();
295    }
296
297    /**
298     * Returns UnsupportedOperationException exception.
299     *
300     * @return UnsupportedOperationException exception
301     */
302    private static UnsupportedOperationException throwUnsupportedOperationException() {
303        return new UnsupportedOperationException("Operation is not supported");
304    }
305
306}