View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.configuration2.tree.xpath;
18  
19  import org.apache.commons.configuration2.tree.NodeHandler;
20  import org.apache.commons.configuration2.tree.QueryResult;
21  import org.apache.commons.jxpath.ri.Compiler;
22  import org.apache.commons.jxpath.ri.QName;
23  import org.apache.commons.jxpath.ri.compiler.NodeTest;
24  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
25  import org.apache.commons.jxpath.ri.model.NodePointer;
26  
27  /**
28   * <p>
29   * A specialized {@code NodePointer} implementation for the attributes of a configuration node.
30   * </p>
31   *
32   * @param <T> the type of the nodes this pointer deals with
33   * @since 2.0
34   */
35  final class ConfigurationAttributePointer<T> extends NodePointer {
36      /**
37       * The serial version UID.
38       */
39      private static final long serialVersionUID = 5504551041716043748L;
40  
41      /** Stores information about the represented attribute. */
42      private final QueryResult<T> attributeResult;
43  
44      /**
45       * Creates a new instance of {@code ConfigurationAttributePointer}.
46       *
47       * @param parent the parent node pointer
48       * @param attrName the name of the managed attribute
49       */
50      public ConfigurationAttributePointer(final ConfigurationNodePointer<T> parent, final String attrName) {
51          super(parent);
52          attributeResult = QueryResult.createAttributeResult(parent.getConfigurationNode(), attrName);
53      }
54  
55      /**
56       * Compares two child node pointers. Attributes do not have any children, so this is just a dummy implementation.
57       *
58       * @param p1 the first pointer
59       * @param p2 the second pointer
60       * @return the order of these pointers
61       */
62      @Override
63      public int compareChildNodePointers(final NodePointer p1, final NodePointer p2) {
64          return 0;
65      }
66  
67      /**
68       * Gets the base value. We return the value.
69       *
70       * @return the base value
71       */
72      @Override
73      public Object getBaseValue() {
74          return getValue();
75      }
76  
77      /**
78       * Gets the immediate node. This is actually a {@link QueryResult} object describing the represented attribute.
79       *
80       * @return the immediate node
81       */
82      @Override
83      public Object getImmediateNode() {
84          return attributeResult;
85      }
86  
87      /**
88       * Gets the length of the represented node. This is always 1.
89       *
90       * @return the length
91       */
92      @Override
93      public int getLength() {
94          return 1;
95      }
96  
97      /**
98       * Gets the name of this node. This is the attribute name.
99       *
100      * @return the name of this node
101      */
102     @Override
103     public QName getName() {
104         return new QName(null, attributeResult.getAttributeName());
105     }
106 
107     /**
108      * Returns a reference to the current node handler. The handler is obtained from the parent pointer.
109      *
110      * @return the node handler
111      */
112     private NodeHandler<T> getNodeHandler() {
113         return getParentPointer().getNodeHandler();
114     }
115 
116     /**
117      * Gets a reference to the parent node pointer.
118      *
119      * @return the parent pointer
120      */
121     public ConfigurationNodePointer<T> getParentPointer() {
122         // safe to cast because the constructor only expects pointers of this
123         // type
124         @SuppressWarnings("unchecked")
125         final ConfigurationNodePointer<T> configurationNodePointer = (ConfigurationNodePointer<T>) getParent();
126         return configurationNodePointer;
127     }
128 
129     /**
130      * Returns the value of this node.
131      *
132      * @return this node's value
133      */
134     @Override
135     public Object getValue() {
136         return attributeResult.getAttributeValue(getNodeHandler());
137     }
138 
139     /**
140      * Returns a flag whether this node is an attribute. Of course, this is the case.
141      *
142      * @return the attribute flag
143      */
144     @Override
145     public boolean isAttribute() {
146         return true;
147     }
148 
149     /**
150      * Returns a flag whether the represented node is a collection. This is not the case.
151      *
152      * @return the collection flag
153      */
154     @Override
155     public boolean isCollection() {
156         return false;
157     }
158 
159     /**
160      * Returns a flag whether the represented node is a leaf. This is the case for attributes.
161      *
162      * @return the leaf flag
163      */
164     @Override
165     public boolean isLeaf() {
166         return true;
167     }
168 
169     /**
170      * Sets the value of this node. This is not supported because the classes of the {@code XPathExpressionEngine} are only
171      * used for queries. This implementation always throws an exception.
172      *
173      * @param value the new value
174      */
175     @Override
176     public void setValue(final Object value) {
177         throw new UnsupportedOperationException("Updating the value is not supported!");
178     }
179 
180     /**
181      * Tests if this node matches the given test. Attribute nodes are text nodes, too, because they can contain a value.
182      *
183      * @param test the test object
184      * @return a flag if this node corresponds to the test
185      */
186     @Override
187     public boolean testNode(final NodeTest test) {
188         if (test instanceof NodeTypeTest && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT) {
189             return true;
190         }
191         return super.testNode(test);
192     }
193 }