/*
* 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.configuration.tree.xpath;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.apache.commons.configuration.tree.ConfigurationNode;
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</code> implementation for configuration nodes.
* </p>
* <p>
* This is needed for queries using JXPath.
* </p>
*
* @since 1.3
* @author Oliver Heger
* @version $Id: ConfigurationNodePointer.java 439648 2006-09-02 20:42:10Z oheger $
*/
class ConfigurationNodePointer extends NodePointer
{
/**
* The serial version UID.
*/
private static final long serialVersionUID = -1087475639680007713L;
/** Stores the associated configuration node. */
private ConfigurationNode node;
/**
* Creates a new instance of <code>ConfigurationNodePointer</code>.
*
* @param node the node
* @param locale the locale
*/
public ConfigurationNodePointer(ConfigurationNode node, Locale locale)
{
super(null, locale);
this.node = node;
}
/**
* Creates a new instance of <code>ConfigurationNodePointer</code> and
* initializes it with its parent pointer.
*
* @param parent the parent pointer
* @param node the associated node
*/
public ConfigurationNodePointer(NodePointer parent, ConfigurationNode node)
{
super(parent);
this.node = node;
}
/**
* 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
*/
public boolean isLeaf()
{
return node.getChildrenCount() < 1;
}
/**
* Returns a flag if this node is a collection. This is not the case.
*
* @return the collection flag
*/
public boolean isCollection()
{
return false;
}
/**
* Returns this node's length. This is always 1.
*
* @return the node's length
*/
public int getLength()
{
return 1;
}
/**
* Checks whether this node pointer refers to an attribute node. This method
* checks the attribute flag of the associated configuration node.
*
* @return the attribute flag
*/
public boolean isAttribute()
{
return node.isAttribute();
}
/**
* Returns this node's name.
*
* @return the name
*/
public QName getName()
{
return new QName(null, node.getName());
}
/**
* Returns this node's base value. This is the associated configuration
* node.
*
* @return the base value
*/
public Object getBaseValue()
{
return node;
}
/**
* Returns the immediate node. This is the associated configuration node.
*
* @return the immediate node
*/
public Object getImmediateNode()
{
return node;
}
/**
* Returns the value of this node.
*
* @return the represented node's value
*/
public Object getValue()
{
return node.getValue();
}
/**
* Sets the value of this node.
*
* @param value the new value
*/
public void setValue(Object value)
{
node.setValue(value);
}
/**
* Compares two child node pointers.
*
* @param pointer1 one pointer
* @param pointer2 another pointer
* @return a flag, which pointer should be sorted first
*/
public int compareChildNodePointers(NodePointer pointer1,
NodePointer pointer2)
{
ConfigurationNode node1 = (ConfigurationNode) pointer1.getBaseValue();
ConfigurationNode node2 = (ConfigurationNode) pointer2.getBaseValue();
// attributes will be sorted before child nodes
if (node1.isAttribute() && !node2.isAttribute())
{
return -1;
}
else if (node2.isAttribute() && !node1.isAttribute())
{
return 1;
}
else
{
// sort based on the occurrence in the sub node list
List subNodes = node1.isAttribute() ? node.getAttributes() : node
.getChildren();
for (Iterator it = subNodes.iterator(); it.hasNext();)
{
ConfigurationNode child = (ConfigurationNode) it.next();
if (child == node1)
{
return -1;
}
else if (child == node2)
{
return 1;
}
}
return 0; // should not happen
}
}
/**
* Returns an iterator for the attributes that match the given name.
*
* @param name the attribute name
* @return the iterator for the attributes
*/
public NodeIterator attributeIterator(QName name)
{
return new ConfigurationNodeIteratorAttribute(this, name);
}
/**
* 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
*/
public NodeIterator childIterator(NodeTest test, boolean reverse,
NodePointer startWith)
{
return new ConfigurationNodeIteratorChildren(this, test, reverse,
startWith);
}
/**
* 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
*/
public boolean testNode(NodeTest test)
{
if (test instanceof NodeTypeTest
&& ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT)
{
return true;
}
return super.testNode(test);
}
}
|