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


Reply via email to