1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml.util;
18
19 import java.util.AbstractList;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25
26 import javax.xml.namespace.QName;
27
28 import org.opensaml.xml.XMLObject;
29
30
31
32
33
34
35 public class IndexedXMLObjectChildrenList<ElementType extends XMLObject> extends XMLObjectChildrenList<ElementType> {
36
37
38 private Map<QName, ArrayList<ElementType>> objectIndex;
39
40
41
42
43
44
45 public IndexedXMLObjectChildrenList(XMLObject parent) {
46 super(parent);
47 objectIndex = new ConcurrentHashMap<QName, ArrayList<ElementType>>();
48 }
49
50
51
52
53
54
55
56 public IndexedXMLObjectChildrenList(XMLObject parent, Collection<ElementType> col) {
57 super(parent);
58 objectIndex = new ConcurrentHashMap<QName, ArrayList<ElementType>>();
59 addAll(col);
60 }
61
62
63 public void clear() {
64 super.clear();
65 objectIndex.clear();
66 }
67
68
69
70
71
72
73
74
75 public List<ElementType> get(QName typeOrName) {
76 return objectIndex.get(typeOrName);
77 }
78
79
80
81
82
83
84
85
86
87 public ElementType set(int index, ElementType element) {
88 ElementType returnValue = super.set(index, element);
89
90 removeElementFromIndex(returnValue);
91
92 indexElement(element);
93 return returnValue;
94 }
95
96
97
98
99
100
101
102
103 public void add(int index, ElementType element) {
104 super.add(index, element);
105 indexElement(element);
106 }
107
108
109
110
111
112
113
114
115
116 public ElementType remove(int index) {
117 ElementType returnValue = super.remove(index);
118
119 removeElementFromIndex(returnValue);
120
121 return returnValue;
122 }
123
124
125
126
127
128
129
130
131 public boolean remove(ElementType element) {
132 boolean elementRemoved = false;
133
134 elementRemoved = super.remove(element);
135 if (elementRemoved) {
136 removeElementFromIndex(element);
137 }
138
139 return elementRemoved;
140 }
141
142
143
144
145
146
147
148
149
150
151 public List<? extends ElementType> subList(QName index) {
152 if (!objectIndex.containsKey(index)) {
153 objectIndex.put(index, new ArrayList<ElementType>());
154 }
155
156 return new ListView<ElementType>(this, index);
157 }
158
159
160
161
162
163
164 protected void indexElement(ElementType element) {
165 if (element == null) {
166 return;
167 }
168
169 QName type = element.getSchemaType();
170 if (type != null) {
171 indexElement(type, element);
172 }
173
174 indexElement(element.getElementQName(), element);
175 }
176
177
178
179
180
181
182
183 protected void indexElement(QName index, ElementType element) {
184 ArrayList<ElementType> objects = objectIndex.get(index);
185 if (objects == null) {
186 objects = new ArrayList<ElementType>();
187 objectIndex.put(index, objects);
188 }
189
190 objects.add(element);
191 }
192
193
194
195
196
197
198 protected void removeElementFromIndex(ElementType element) {
199 if (element == null) {
200 return;
201 }
202
203 QName type = element.getSchemaType();
204 if (type != null) {
205 removeElementFromIndex(type, element);
206 }
207
208 removeElementFromIndex(element.getElementQName(), element);
209 }
210
211
212
213
214
215
216
217 protected void removeElementFromIndex(QName index, ElementType element) {
218 ArrayList<ElementType> objects = objectIndex.get(index);
219 if (objects != null) {
220 objects.remove(element);
221 }
222
223 if (objects.size() == 0) {
224 objectIndex.remove(index);
225 }
226 }
227 }
228
229
230
231
232
233
234
235 class ListView<ElementType extends XMLObject> extends AbstractList<ElementType> {
236
237
238 private IndexedXMLObjectChildrenList<ElementType> backingList;
239
240
241 private QName index;
242
243
244 private List<ElementType> indexList;
245
246
247
248
249
250
251
252 public ListView(IndexedXMLObjectChildrenList<ElementType> newBackingList, QName newIndex) {
253 backingList = newBackingList;
254 index = newIndex;
255 indexList = backingList.get(index);
256 }
257
258
259
260
261
262
263
264
265 public boolean contains(ElementType element) {
266 return indexList.contains(element);
267 }
268
269
270 public ElementType get(int newIndex) {
271 return indexList.get(newIndex);
272 }
273
274
275 public int size() {
276 return indexList.size();
277 }
278
279
280 public ElementType set(int newIndex, ElementType element) {
281
282 if (newIndex < 0 && newIndex > indexList.size()) {
283 throw new IndexOutOfBoundsException();
284 }
285
286 ElementType replacedElement;
287 int elementIndex;
288
289 replacedElement = indexList.get(newIndex);
290 elementIndex = backingList.indexOf(replacedElement);
291 backingList.set(elementIndex, element);
292
293 return replacedElement;
294 }
295
296
297 public void add(int newIndex, ElementType element) {
298 indexCheck(element);
299 backingList.add(element);
300 }
301
302
303 public ElementType remove(int newIndex) {
304 return backingList.remove(newIndex);
305 }
306
307
308
309
310
311
312
313
314 protected void indexCheck(ElementType element) throws IllegalArgumentException {
315 if (index.equals(element.getSchemaType()) || index.equals(element.getElementQName())) {
316 return;
317 } else {
318 throw new IllegalArgumentException("Element " + element.getElementQName() + " is not of type " + index);
319 }
320 }
321 }