1
2
3
4
5
6
7
8
9
10 package org.dom4j.util;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17
18 import org.dom4j.Attribute;
19 import org.dom4j.Element;
20 import org.dom4j.Node;
21 import org.dom4j.QName;
22 import org.dom4j.tree.BackedList;
23 import org.dom4j.tree.DefaultElement;
24
25 /*** <p><code>IndexedElement</code> is an implementation of {@link Element}
26 * which maintains an index of the attributes and elements it contains to
27 * optimise lookups via name.</p>
28 *
29 * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
30 * @version $Revision: 1.8 $
31 */
32 public class IndexedElement extends DefaultElement {
33
34 /*** Lazily constructed index for elements */
35 private Map elementIndex;
36
37 /*** Lazily constructed index for attributes */
38 private Map attributeIndex;
39
40
41 public IndexedElement(String name) {
42 super(name);
43 }
44
45 public IndexedElement(QName qname) {
46 super(qname);
47 }
48
49 public IndexedElement(QName qname, int attributeCount) {
50 super(qname, attributeCount);
51 }
52
53 public Attribute attribute(String name) {
54 return (Attribute) attributeIndex().get(name);
55 }
56
57 public Attribute attribute(QName qName) {
58 return (Attribute) attributeIndex().get(qName);
59 }
60
61 public Element element(String name) {
62 return asElement( elementIndex().get(name) );
63 }
64
65 public Element element(QName qName) {
66 return asElement( elementIndex().get(qName) );
67 }
68
69 public List elements(String name) {
70 return asElementList( elementIndex().get(name) );
71 }
72
73 public List elements(QName qName) {
74 return asElementList( elementIndex().get(qName) );
75 }
76
77
78
79
80
81 protected Element asElement(Object object) {
82 if ( object instanceof Element ) {
83 return (Element) object;
84 }
85 else if ( object != null ) {
86 List list = (List) object;
87 if ( list.size() >= 1 ) {
88 return (Element) list.get(0);
89 }
90 }
91 return null;
92 }
93
94 protected List asElementList(Object object) {
95 if ( object instanceof Element ) {
96 return createSingleResultList( object );
97 }
98 else if ( object != null ) {
99 List list = (List) object;
100 BackedList answer = createResultList();
101 for ( int i = 0, size = list.size(); i < size; i++ ) {
102 answer.addLocal( list.get(i) );
103 }
104 return answer;
105 }
106 return createEmptyList();
107 }
108
109 /***
110 * @deprecated WILL BE REMOVED IN dom4j-1.6 !!
111 */
112 protected Iterator asElementIterator(Object object) {
113 return asElementList(object).iterator();
114 }
115
116
117
118
119 protected void addNode(Node node) {
120 super.addNode(node);
121 if ( elementIndex != null && node instanceof Element ) {
122 addToElementIndex( (Element) node );
123 }
124 else if ( attributeIndex != null && node instanceof Attribute ) {
125 addToAttributeIndex( (Attribute) node );
126 }
127 }
128
129 protected boolean removeNode(Node node) {
130 if ( super.removeNode(node) ) {
131 if ( elementIndex != null && node instanceof Element ) {
132 removeFromElementIndex( (Element) node );
133 }
134 else if ( attributeIndex != null && node instanceof Attribute ) {
135 removeFromAttributeIndex( (Attribute) node );
136 }
137 return true;
138 }
139 return false;
140 }
141
142 protected Map attributeIndex() {
143 if ( attributeIndex == null ) {
144 attributeIndex = createAttributeIndex();
145 for (Iterator iter = attributeIterator(); iter.hasNext(); ) {
146 addToAttributeIndex( (Attribute) iter.next() );
147 }
148 }
149 return attributeIndex;
150 }
151
152 protected Map elementIndex() {
153 if ( elementIndex == null ) {
154 elementIndex = createElementIndex();
155 for (Iterator iter = elementIterator(); iter.hasNext(); ) {
156 addToElementIndex( (Element) iter.next() );
157 }
158 }
159 return elementIndex;
160 }
161
162 /*** A Factory Method to create the index for attributes
163 */
164 protected Map createAttributeIndex() {
165 Map answer = createIndex();
166 return answer;
167 }
168
169 /*** A Factory Method to create the index for elements
170 */
171 protected Map createElementIndex() {
172 Map answer = createIndex();
173 return answer;
174 }
175
176 protected void addToElementIndex(Element element) {
177 QName qName = element.getQName();
178 String name = qName.getName();
179 addToElementIndex(qName, element);
180 addToElementIndex(name, element);
181 }
182
183 protected void addToElementIndex(Object key, Element value) {
184 Object oldValue = elementIndex.get(key);
185 if (oldValue == null) {
186 elementIndex.put(key, value);
187 }
188 else {
189 if ( oldValue instanceof List ) {
190 List list = (List) oldValue;
191 list.add(value);
192 }
193 else {
194 List list = createList();
195 list.add(oldValue);
196 list.add(value);
197 elementIndex.put(key, list);
198 }
199 }
200 }
201
202 protected void removeFromElementIndex(Element element) {
203 QName qName = element.getQName();
204 String name = qName.getName();
205 removeFromElementIndex(qName, element);
206 removeFromElementIndex(name, element);
207 }
208
209 protected void removeFromElementIndex(Object key, Element value) {
210 Object oldValue = elementIndex.get(key);
211 if ( oldValue instanceof List ) {
212 List list = (List) oldValue;
213 list.remove(value);
214 }
215 else {
216 elementIndex.remove(key);
217 }
218 }
219
220
221 protected void addToAttributeIndex(Attribute attribute) {
222 QName qName = attribute.getQName();
223 String name = qName.getName();
224 addToAttributeIndex(qName, attribute);
225 addToAttributeIndex(name, attribute);
226 }
227
228 protected void addToAttributeIndex(Object key, Attribute value) {
229 Object oldValue = attributeIndex.get(key);
230 if (oldValue != null) {
231 attributeIndex.put(key, value);
232 }
233 }
234
235 protected void removeFromAttributeIndex(Attribute attribute) {
236 QName qName = attribute.getQName();
237 String name = qName.getName();
238 removeFromAttributeIndex(qName, attribute);
239 removeFromAttributeIndex(name, attribute);
240 }
241
242 protected void removeFromAttributeIndex(Object key, Attribute value) {
243 Object oldValue = attributeIndex.get(key);
244 if ( oldValue != null && oldValue.equals( value ) ) {
245 attributeIndex.remove(key);
246 }
247 }
248
249 /*** Factory method to return a new map implementation for indices
250 */
251 protected Map createIndex() {
252 return new HashMap();
253 }
254
255 /*** Factory method to return a list implementation for indices
256 */
257 protected List createList() {
258 return new ArrayList();
259 }
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308