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 * 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 }