Author: oheger Date: Fri Feb 7 20:35:42 2014 New Revision: 1565796 URL: http://svn.apache.org/r1565796 Log: Added a special NodePointer implementation for attributes.
This implementation wraps a single attribute of a configuration node which is represented by a QueryResult object. Added: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationAttributePointer.java commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/xpath/TestConfigurationAttributePointer.java Added: commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationAttributePointer.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationAttributePointer.java?rev=1565796&view=auto ============================================================================== --- commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationAttributePointer.java (added) +++ commons/proper/configuration/branches/immutableNodes/src/main/java/org/apache/commons/configuration/tree/xpath/ConfigurationAttributePointer.java Fri Feb 7 20:35:42 2014 @@ -0,0 +1,225 @@ +/* + * 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 org.apache.commons.configuration.tree.NodeHandler; +import org.apache.commons.configuration.tree.QueryResult; +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.NodePointer; + +/** + * <p> + * A specialized {@code NodePointer} implementation for the attributes of + * a configuration node. + * </p> + * + * @version $Id $ + * @since 2.0 + * @param <T> the type of the nodes this pointer deals with + */ +class ConfigurationAttributePointer<T> extends NodePointer +{ + /** + * The serial version UID. + */ + private static final long serialVersionUID = 5504551041716043748L; + + /** Stores information about the represented attribute. */ + private final QueryResult<T> attributeResult; + + /** + * Creates a new instance of {@code ConfigurationAttributePointer}. + * + * @param parent the parent node pointer + * @param attrName the name of the managed attribute + */ + public ConfigurationAttributePointer(ConfigurationNodePointer<T> parent, + String attrName) + { + super(parent); + attributeResult = + QueryResult.createAttributeResult( + parent.getConfigurationNode(), attrName); + } + + /** + * Returns a reference to the parent node pointer. + * + * @return the parent pointer + */ + public ConfigurationNodePointer<T> getParentPointer() + { + // safe to cast because the constructor only expects pointers of this + // type + @SuppressWarnings("unchecked") + ConfigurationNodePointer<T> configurationNodePointer = + (ConfigurationNodePointer<T>) getParent(); + return configurationNodePointer; + } + + /** + * Compares two child node pointers. Attributes do not have any children, so + * this is just a dummy implementation. + * + * @param p1 the first pointer + * @param p2 the second pointer + * @return the order of these pointers + */ + @Override + public int compareChildNodePointers(NodePointer p1, NodePointer p2) + { + return 0; + } + + /** + * Returns the base value. We return the value. + * + * @return the base value + */ + @Override + public Object getBaseValue() + { + return getValue(); + } + + /** + * Returns the immediate node. This is actually a {@link QueryResult} + * object describing the represented attribute. + * + * @return the immediate node + */ + @Override + public Object getImmediateNode() + { + return attributeResult; + } + + /** + * Returns the length of the represented node. This is always 1. + * + * @return the length + */ + @Override + public int getLength() + { + return 1; + } + + /** + * Returns the name of this node. This is the attribute name. + * + * @return the name of this node + */ + @Override + public QName getName() + { + return new QName(null, attributeResult.getAttributeName()); + } + + /** + * Returns a flag whether the represented node is a collection. This is not + * the case. + * + * @return the collection flag + */ + @Override + public boolean isCollection() + { + return false; + } + + /** + * Returns a flag whether the represented node is a leaf. This is the case + * for attributes. + * + * @return the leaf flag + */ + @Override + public boolean isLeaf() + { + return true; + } + + /** + * Returns a flag whether this node is an attribute. Of course, this is the + * case. + * + * @return the attribute flag + */ + @Override + public boolean isAttribute() + { + return true; + } + + /** + * Returns the value of this node. + * + * @return this node's value + */ + @Override + public Object getValue() + { + return attributeResult.getAttributeValue(getNodeHandler()); + } + + /** + * Sets the value of this node. This is not supported because the classes of + * the {@code XPathExpressionEngine} are only used for queries. This + * implementation always throws an exception. + * + * @param value the new value + */ + @Override + public void setValue(Object value) + { + throw new UnsupportedOperationException( + "Updating the value is not supported!"); + } + + /** + * Tests if this node matches the given test. Attribute 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(NodeTest test) + { + if (test instanceof NodeTypeTest + && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT) + { + return true; + } + return super.testNode(test); + } + + /** + * Returns a reference to the current node handler. The handler is obtained + * from the parent pointer. + * + * @return the node handler + */ + private NodeHandler<T> getNodeHandler() + { + return getParentPointer().getNodeHandler(); + } +} Added: commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/xpath/TestConfigurationAttributePointer.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/xpath/TestConfigurationAttributePointer.java?rev=1565796&view=auto ============================================================================== --- commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/xpath/TestConfigurationAttributePointer.java (added) +++ commons/proper/configuration/branches/immutableNodes/src/test/java/org/apache/commons/configuration/tree/xpath/TestConfigurationAttributePointer.java Fri Feb 7 20:35:42 2014 @@ -0,0 +1,201 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.Locale; + +import org.apache.commons.configuration.tree.ImmutableNode; +import org.apache.commons.configuration.tree.InMemoryNodeModel; +import org.apache.commons.configuration.tree.QueryResult; +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.junit.Before; +import org.junit.Test; + +/** + * Test class for {@code ConfigurationAttributePointer}. + * + * @version $Id $ + */ +public class TestConfigurationAttributePointer +{ + /** Constant for the name of the test attribute. */ + private static final String ATTR_NAME = "myAttr"; + + /** Constant for the value of the test attribute. */ + private static final String ATTR_VALUE = "myValue"; + + /** Stores the parent node pointer. */ + private ConfigurationNodePointer<ImmutableNode> parent; + + /** The attribute pointer to be tested. */ + private ConfigurationAttributePointer<ImmutableNode> pointer; + + @Before + public void setUp() throws Exception + { + ImmutableNode.Builder ndBuilder = new ImmutableNode.Builder(); + ndBuilder.name("parent").addAttribute(ATTR_NAME, ATTR_VALUE); + ImmutableNode nd = ndBuilder.create(); + parent = + new ConfigurationNodePointer<ImmutableNode>(nd, Locale.ENGLISH, + new InMemoryNodeModel(nd)); + pointer = + new ConfigurationAttributePointer<ImmutableNode>(parent, + ATTR_NAME); + } + + /** + * Tests whether the correct pointer is returned. + */ + @Test + public void testGetParentPointer() + { + assertSame("Wrong parent pointer", parent, pointer.getParentPointer()); + } + + /** + * Tests querying the base value. + */ + @Test + public void testGetBaseValue() + { + assertEquals("Wrong base value", ATTR_VALUE, pointer.getBaseValue()); + } + + /** + * Tests querying the immediate node. Here a proxy for an attribute node + * should be returned. + */ + @Test + public void testGetImmediateNode() + { + Object node = pointer.getImmediateNode(); + assertTrue("Wrong node class", node instanceof QueryResult); + QueryResult<?> proxy = (QueryResult<?>) node; + assertTrue("No attribute result", proxy.isAttributeResult()); + assertEquals("Wrong parent node", parent.getConfigurationNode(), + proxy.getNode()); + assertEquals("Wrong attribute name", ATTR_NAME, + proxy.getAttributeName()); + } + + /** + * Tests the length. + */ + @Test + public void testGetLength() + { + assertEquals("Wrong length", 1, pointer.getLength()); + } + + /** + * Tests querying the node name. + */ + @Test + public void testGetName() + { + QName name = pointer.getName(); + assertEquals("Wrong name", ATTR_NAME, name.getName()); + assertNull("Prefix not null", name.getPrefix()); + } + + /** + * Tests the collection flag. + */ + @Test + public void testIsCollection() + { + assertFalse("Wrong collection flag", pointer.isCollection()); + } + + /** + * Tests the leaf flag. + */ + @Test + public void testIsLeaf() + { + assertTrue("Wrong leaf flag", pointer.isLeaf()); + } + + /** + * Tests the attribute flag. + */ + @Test + public void testIsAttribute() + { + assertTrue("Not an attribute", pointer.isAttribute()); + } + + /** + * Tests querying the attribute's value. + */ + @Test + public void testGetValue() + { + assertEquals("Wrong value", ATTR_VALUE, pointer.getValue()); + } + + /** + * Tries to set a new value. + */ + @Test(expected = UnsupportedOperationException.class) + public void testSetValue() + { + pointer.setValue("newValue"); + } + + /** + * Tests querying an iterator for attributes. Result should be null. + */ + @Test + public void testAttributeIterator() + { + assertNull("Returned an attribute iterator", pointer + .attributeIterator(new QName(null, "test"))); + } + + /** + * Tests querying an iterator for children. Result should be null. + */ + @Test + public void testChildIterator() + { + assertNull("Returned an iterator for children", pointer.childIterator( + null, false, null)); + } + + /** + * Tests the testNode() method. + */ + @Test + public void testTestNode() + { + NodeTest test = new NodeTypeTest(Compiler.NODE_TYPE_TEXT); + assertTrue("No a text node", pointer.testNode(test)); + test = new NodeTypeTest(Compiler.NODE_TYPE_COMMENT); + assertFalse("A comment node", pointer.testNode(test)); + } +}