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