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   * @since 2.0
33   * @param <T> the type of the nodes this pointer deals with
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       * Gets a reference to the parent node pointer.
57       *
58       * @return the parent pointer
59       */
60      public ConfigurationNodePointer<T> getParentPointer() {
61          // safe to cast because the constructor only expects pointers of this
62          // type
63          @SuppressWarnings("unchecked")
64          final ConfigurationNodePointer<T> configurationNodePointer = (ConfigurationNodePointer<T>) getParent();
65          return configurationNodePointer;
66      }
67  
68      /**
69       * Compares two child node pointers. Attributes do not have any children, so this is just a dummy implementation.
70       *
71       * @param p1 the first pointer
72       * @param p2 the second pointer
73       * @return the order of these pointers
74       */
75      @Override
76      public int compareChildNodePointers(final NodePointer p1, final NodePointer p2) {
77          return 0;
78      }
79  
80      /**
81       * Gets the base value. We return the value.
82       *
83       * @return the base value
84       */
85      @Override
86      public Object getBaseValue() {
87          return getValue();
88      }
89  
90      /**
91       * Gets the immediate node. This is actually a {@link QueryResult} object describing the represented attribute.
92       *
93       * @return the immediate node
94       */
95      @Override
96      public Object getImmediateNode() {
97          return attributeResult;
98      }
99  
100     /**
101      * Gets the length of the represented node. This is always 1.
102      *
103      * @return the length
104      */
105     @Override
106     public int getLength() {
107         return 1;
108     }
109 
110     /**
111      * Gets the name of this node. This is the attribute name.
112      *
113      * @return the name of this node
114      */
115     @Override
116     public QName getName() {
117         return new QName(null, attributeResult.getAttributeName());
118     }
119 
120     /**
121      * Returns a flag whether the represented node is a collection. This is not the case.
122      *
123      * @return the collection flag
124      */
125     @Override
126     public boolean isCollection() {
127         return false;
128     }
129 
130     /**
131      * Returns a flag whether the represented node is a leaf. This is the case for attributes.
132      *
133      * @return the leaf flag
134      */
135     @Override
136     public boolean isLeaf() {
137         return true;
138     }
139 
140     /**
141      * Returns a flag whether this node is an attribute. Of course, this is the case.
142      *
143      * @return the attribute flag
144      */
145     @Override
146     public boolean isAttribute() {
147         return true;
148     }
149 
150     /**
151      * Returns the value of this node.
152      *
153      * @return this node's value
154      */
155     @Override
156     public Object getValue() {
157         return attributeResult.getAttributeValue(getNodeHandler());
158     }
159 
160     /**
161      * Sets the value of this node. This is not supported because the classes of the {@code XPathExpressionEngine} are only
162      * used for queries. This implementation always throws an exception.
163      *
164      * @param value the new value
165      */
166     @Override
167     public void setValue(final Object value) {
168         throw new UnsupportedOperationException("Updating the value is not supported!");
169     }
170 
171     /**
172      * Tests if this node matches the given test. Attribute nodes are text nodes, too, because they can contain a value.
173      *
174      * @param test the test object
175      * @return a flag if this node corresponds to the test
176      */
177     @Override
178     public boolean testNode(final NodeTest test) {
179         if (test instanceof NodeTypeTest && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT) {
180             return true;
181         }
182         return super.testNode(test);
183     }
184 
185     /**
186      * Returns a reference to the current node handler. The handler is obtained from the parent pointer.
187      *
188      * @return the node handler
189      */
190     private NodeHandler<T> getNodeHandler() {
191         return getParentPointer().getNodeHandler();
192     }
193 }