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