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));
+ }
+}