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