ConfigurationNodePointer.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.configuration2.tree.xpath;
- import java.util.Locale;
- import org.apache.commons.configuration2.tree.NodeHandler;
- import org.apache.commons.jxpath.ri.Compiler;
- import org.apache.commons.jxpath.ri.QName;
- import org.apache.commons.jxpath.ri.compiler.NodeTest;
- import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
- import org.apache.commons.jxpath.ri.model.NodeIterator;
- import org.apache.commons.jxpath.ri.model.NodePointer;
- /**
- * <p>
- * A specific {@code NodePointer} implementation for configuration nodes.
- * </p>
- * <p>
- * This is needed for queries using JXPath.
- * </p>
- *
- * @param <T> the type of the nodes this pointer deals with
- * @since 1.3
- */
- final class ConfigurationNodePointer<T> extends NodePointer {
- /**
- * The serial version UID.
- */
- private static final long serialVersionUID = -1087475639680007713L;
- /** The node handler. */
- private final NodeHandler<T> handler;
- /** Stores the associated node. */
- private final T node;
- /**
- * Creates a new instance of {@code ConfigurationNodePointer} and initializes it with its parent pointer.
- *
- * @param parent the parent pointer
- * @param node the associated node
- * @param handler the {@code NodeHandler}
- */
- public ConfigurationNodePointer(final ConfigurationNodePointer<T> parent, final T node, final NodeHandler<T> handler) {
- super(parent);
- this.node = node;
- this.handler = handler;
- }
- /**
- * Creates a new instance of {@code ConfigurationNodePointer} pointing to the specified node.
- *
- * @param node the wrapped node
- * @param locale the locale
- * @param handler the {@code NodeHandler}
- */
- public ConfigurationNodePointer(final T node, final Locale locale, final NodeHandler<T> handler) {
- super(null, locale);
- this.node = node;
- this.handler = handler;
- }
- /**
- * Returns an iterator for the attributes that match the given name.
- *
- * @param qName the attribute name
- * @return the iterator for the attributes
- */
- @Override
- public NodeIterator attributeIterator(final QName qName) {
- return new ConfigurationNodeIteratorAttribute<>(this, qName);
- }
- /**
- * Casts the given child pointer to a node pointer of this type. This is a bit dangerous. However, in a typical setup,
- * child node pointers can only be created by this instance which ensures that they are of the correct type. Therefore,
- * this cast is safe.
- *
- * @param p the {@code NodePointer} to cast
- * @return the resulting {@code ConfigurationNodePointer}
- */
- private ConfigurationNodePointer<T> castPointer(final NodePointer p) {
- @SuppressWarnings("unchecked") // see method comment
- final ConfigurationNodePointer<T> result = (ConfigurationNodePointer<T>) p;
- return result;
- }
- /**
- * Returns an iterator for the children of this pointer that match the given test object.
- *
- * @param test the test object
- * @param reverse the reverse flag
- * @param startWith the start value of the iteration
- */
- @Override
- public NodeIterator childIterator(final NodeTest test, final boolean reverse, final NodePointer startWith) {
- return new ConfigurationNodeIteratorChildren<>(this, test, reverse, castPointer(startWith));
- }
- /**
- * Compares two child node pointers.
- *
- * @param pointer1 one pointer
- * @param pointer2 another pointer
- * @return a flag, which pointer should be sorted first
- */
- @Override
- public int compareChildNodePointers(final NodePointer pointer1, final NodePointer pointer2) {
- final Object node1 = pointer1.getBaseValue();
- final Object node2 = pointer2.getBaseValue();
- // sort based on the occurrence in the sub node list
- for (final T child : getNodeHandler().getChildren(node)) {
- if (child == node1) {
- return -1;
- }
- if (child == node2) {
- return 1;
- }
- }
- return 0; // should not happen
- }
- /**
- * Gets this node's base value. This is the associated configuration node.
- *
- * @return the base value
- */
- @Override
- public Object getBaseValue() {
- return node;
- }
- /**
- * Gets the wrapped configuration node.
- *
- * @return the wrapped node
- */
- public T getConfigurationNode() {
- return node;
- }
- /**
- * Gets the immediate node. This is the associated configuration node.
- *
- * @return the immediate node
- */
- @Override
- public Object getImmediateNode() {
- return node;
- }
- /**
- * Gets this node's length. This is always 1.
- *
- * @return the node's length
- */
- @Override
- public int getLength() {
- return 1;
- }
- /**
- * Gets this node's name.
- *
- * @return the name
- */
- @Override
- public QName getName() {
- return new QName(null, getNodeHandler().nodeName(node));
- }
- /**
- * Gets the {@code NodeHandler} used by this instance.
- *
- * @return the {@code NodeHandler}
- */
- public NodeHandler<T> getNodeHandler() {
- return handler;
- }
- /**
- * Gets the value of this node.
- *
- * @return the represented node's value
- */
- @Override
- public Object getValue() {
- return getNodeHandler().getValue(node);
- }
- /**
- * Checks whether this node pointer refers to an attribute node. This is not the case.
- *
- * @return the attribute flag
- */
- @Override
- public boolean isAttribute() {
- return false;
- }
- /**
- * Returns a flag if this node is a collection. This is not the case.
- *
- * @return the collection flag
- */
- @Override
- public boolean isCollection() {
- return false;
- }
- /**
- * Returns a flag whether this node is a leaf. This is the case if there are no child nodes.
- *
- * @return a flag if this node is a leaf
- */
- @Override
- public boolean isLeaf() {
- return getNodeHandler().getChildrenCount(node, null) < 1;
- }
- /**
- * Sets the value of this node. This is not supported, so always an exception is thrown.
- *
- * @param value the new value
- */
- @Override
- public void setValue(final Object value) {
- throw new UnsupportedOperationException("Node value cannot be set!");
- }
- /**
- * Tests if this node matches the given test. Configuration nodes are text nodes, too because they can contain a value.
- *
- * @param test the test object
- * @return a flag if this node corresponds to the test
- */
- @Override
- public boolean testNode(final NodeTest test) {
- if (test instanceof NodeTypeTest && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT) {
- return true;
- }
- return super.testNode(test);
- }
- }