1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration.tree.xpath;
18
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Locale;
22
23 import org.apache.commons.configuration.tree.ConfigurationNode;
24 import org.apache.commons.jxpath.ri.Compiler;
25 import org.apache.commons.jxpath.ri.QName;
26 import org.apache.commons.jxpath.ri.compiler.NodeTest;
27 import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
28 import org.apache.commons.jxpath.ri.model.NodeIterator;
29 import org.apache.commons.jxpath.ri.model.NodePointer;
30
31 /***
32 * <p>
33 * A specific <code>NodePointer</code> implementation for configuration nodes.
34 * </p>
35 * <p>
36 * This is needed for queries using JXPath.
37 * </p>
38 *
39 * @since 1.3
40 * @author Oliver Heger
41 * @version $Id: ConfigurationNodePointer.java 439648 2006-09-02 20:42:10Z oheger $
42 */
43 class ConfigurationNodePointer extends NodePointer
44 {
45 /***
46 * The serial version UID.
47 */
48 private static final long serialVersionUID = -1087475639680007713L;
49
50 /*** Stores the associated configuration node. */
51 private ConfigurationNode node;
52
53 /***
54 * Creates a new instance of <code>ConfigurationNodePointer</code>.
55 *
56 * @param node the node
57 * @param locale the locale
58 */
59 public ConfigurationNodePointer(ConfigurationNode node, Locale locale)
60 {
61 super(null, locale);
62 this.node = node;
63 }
64
65 /***
66 * Creates a new instance of <code>ConfigurationNodePointer</code> and
67 * initializes it with its parent pointer.
68 *
69 * @param parent the parent pointer
70 * @param node the associated node
71 */
72 public ConfigurationNodePointer(NodePointer parent, ConfigurationNode node)
73 {
74 super(parent);
75 this.node = node;
76 }
77
78 /***
79 * Returns a flag whether this node is a leaf. This is the case if there are
80 * no child nodes.
81 *
82 * @return a flag if this node is a leaf
83 */
84 public boolean isLeaf()
85 {
86 return node.getChildrenCount() < 1;
87 }
88
89 /***
90 * Returns a flag if this node is a collection. This is not the case.
91 *
92 * @return the collection flag
93 */
94 public boolean isCollection()
95 {
96 return false;
97 }
98
99 /***
100 * Returns this node's length. This is always 1.
101 *
102 * @return the node's length
103 */
104 public int getLength()
105 {
106 return 1;
107 }
108
109 /***
110 * Checks whether this node pointer refers to an attribute node. This method
111 * checks the attribute flag of the associated configuration node.
112 *
113 * @return the attribute flag
114 */
115 public boolean isAttribute()
116 {
117 return node.isAttribute();
118 }
119
120 /***
121 * Returns this node's name.
122 *
123 * @return the name
124 */
125 public QName getName()
126 {
127 return new QName(null, node.getName());
128 }
129
130 /***
131 * Returns this node's base value. This is the associated configuration
132 * node.
133 *
134 * @return the base value
135 */
136 public Object getBaseValue()
137 {
138 return node;
139 }
140
141 /***
142 * Returns the immediate node. This is the associated configuration node.
143 *
144 * @return the immediate node
145 */
146 public Object getImmediateNode()
147 {
148 return node;
149 }
150
151 /***
152 * Returns the value of this node.
153 *
154 * @return the represented node's value
155 */
156 public Object getValue()
157 {
158 return node.getValue();
159 }
160
161 /***
162 * Sets the value of this node.
163 *
164 * @param value the new value
165 */
166 public void setValue(Object value)
167 {
168 node.setValue(value);
169 }
170
171 /***
172 * Compares two child node pointers.
173 *
174 * @param pointer1 one pointer
175 * @param pointer2 another pointer
176 * @return a flag, which pointer should be sorted first
177 */
178 public int compareChildNodePointers(NodePointer pointer1,
179 NodePointer pointer2)
180 {
181 ConfigurationNode node1 = (ConfigurationNode) pointer1.getBaseValue();
182 ConfigurationNode node2 = (ConfigurationNode) pointer2.getBaseValue();
183
184
185 if (node1.isAttribute() && !node2.isAttribute())
186 {
187 return -1;
188 }
189 else if (node2.isAttribute() && !node1.isAttribute())
190 {
191 return 1;
192 }
193
194 else
195 {
196
197 List subNodes = node1.isAttribute() ? node.getAttributes() : node
198 .getChildren();
199 for (Iterator it = subNodes.iterator(); it.hasNext();)
200 {
201 ConfigurationNode child = (ConfigurationNode) it.next();
202 if (child == node1)
203 {
204 return -1;
205 }
206 else if (child == node2)
207 {
208 return 1;
209 }
210 }
211 return 0;
212 }
213 }
214
215 /***
216 * Returns an iterator for the attributes that match the given name.
217 *
218 * @param name the attribute name
219 * @return the iterator for the attributes
220 */
221 public NodeIterator attributeIterator(QName name)
222 {
223 return new ConfigurationNodeIteratorAttribute(this, name);
224 }
225
226 /***
227 * Returns an iterator for the children of this pointer that match the given
228 * test object.
229 *
230 * @param test the test object
231 * @param reverse the reverse flag
232 * @param startWith the start value of the iteration
233 */
234 public NodeIterator childIterator(NodeTest test, boolean reverse,
235 NodePointer startWith)
236 {
237 return new ConfigurationNodeIteratorChildren(this, test, reverse,
238 startWith);
239 }
240
241 /***
242 * Tests if this node matches the given test. Configuration nodes are text
243 * nodes, too because they can contain a value.
244 *
245 * @param test the test object
246 * @return a flag if this node corresponds to the test
247 */
248 public boolean testNode(NodeTest test)
249 {
250 if (test instanceof NodeTypeTest
251 && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT)
252 {
253 return true;
254 }
255 return super.testNode(test);
256 }
257 }