1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml;
18
19 import java.util.Collections;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Set;
23
24 import javax.xml.namespace.QName;
25
26 import org.opensaml.xml.util.DatatypeHelper;
27 import org.opensaml.xml.util.IDIndex;
28 import org.opensaml.xml.util.XMLHelper;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import org.w3c.dom.Element;
32
33
34
35
36 public abstract class AbstractXMLObject implements XMLObject {
37
38
39 private final Logger log = LoggerFactory.getLogger(AbstractXMLObject.class);
40
41
42 private XMLObject parent;
43
44
45 private QName elementQname;
46
47
48 private String schemaLocation;
49
50
51 private String noNamespaceSchemaLocation;
52
53
54 private QName typeQname;
55
56
57 private Set<Namespace> namespaces;
58
59
60 private Element dom;
61
62
63
64
65
66 private final IDIndex idIndex;
67
68
69
70
71
72
73
74
75 protected AbstractXMLObject(String namespaceURI, String elementLocalName, String namespacePrefix) {
76 idIndex = new IDIndex(this);
77 namespaces = new HashSet<Namespace>();
78 elementQname = XMLHelper.constructQName(namespaceURI, elementLocalName, namespacePrefix);
79 addNamespace(new Namespace(namespaceURI, namespacePrefix));
80 setElementNamespacePrefix(namespacePrefix);
81 }
82
83
84 public void addNamespace(Namespace namespace) {
85 if (namespace != null) {
86 namespaces.add(namespace);
87 }
88 }
89
90
91 public void detach(){
92 releaseParentDOM(true);
93 parent = null;
94 }
95
96
97 public Element getDOM() {
98 return dom;
99 }
100
101
102 public QName getElementQName() {
103 return new QName(elementQname.getNamespaceURI(), elementQname.getLocalPart(), elementQname.getPrefix());
104 }
105
106
107 public IDIndex getIDIndex() {
108 return idIndex;
109 }
110
111
112 public Set<Namespace> getNamespaces() {
113 return Collections.unmodifiableSet(namespaces);
114 }
115
116
117 public String getNoNamespaceSchemaLocation() {
118 return noNamespaceSchemaLocation;
119 }
120
121
122
123
124
125
126 public XMLObject getParent() {
127 return parent;
128 }
129
130
131 public String getSchemaLocation() {
132 return schemaLocation;
133 }
134
135
136 public QName getSchemaType() {
137 return typeQname;
138 }
139
140
141 public boolean hasChildren() {
142 List<? extends XMLObject> children = getOrderedChildren();
143 return children != null && children.size() > 0;
144 }
145
146
147 public boolean hasParent() {
148 return getParent() != null;
149 }
150
151
152
153
154
155
156
157
158
159
160
161 protected QName prepareForAssignment(QName oldValue, QName newValue) {
162 if (oldValue == null) {
163 if (newValue != null) {
164 Namespace newNamespace = new Namespace(newValue.getNamespaceURI(), newValue.getPrefix());
165 addNamespace(newNamespace);
166 releaseThisandParentDOM();
167 return newValue;
168 } else {
169 return null;
170 }
171 }
172
173 if (!oldValue.equals(newValue)) {
174 if (newValue != null) {
175 Namespace newNamespace = new Namespace(newValue.getNamespaceURI(), newValue.getPrefix());
176 addNamespace(newNamespace);
177 }
178 releaseThisandParentDOM();
179 }
180
181 return newValue;
182 }
183
184
185
186
187
188
189
190
191
192
193
194 protected String prepareForAssignment(String oldValue, String newValue) {
195 String newString = DatatypeHelper.safeTrimOrNullString(newValue);
196
197 if (!DatatypeHelper.safeEquals(oldValue, newString)) {
198 releaseThisandParentDOM();
199 }
200
201 return newString;
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 protected <T extends Object> T prepareForAssignment(T oldValue, T newValue) {
219 if (oldValue == null) {
220 if (newValue != null) {
221 releaseThisandParentDOM();
222 return newValue;
223 } else {
224 return null;
225 }
226 }
227
228 if (!oldValue.equals(newValue)) {
229 releaseThisandParentDOM();
230 }
231
232 return newValue;
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 protected <T extends XMLObject> T prepareForAssignment(T oldValue, T newValue) {
251
252 if (newValue != null && newValue.hasParent()) {
253 throw new IllegalArgumentException(newValue.getClass().getName()
254 + " cannot be added - it is already the child of another SAML Object");
255 }
256
257 if (oldValue == null) {
258 if (newValue != null) {
259 releaseThisandParentDOM();
260 newValue.setParent(this);
261 idIndex.registerIDMappings(newValue.getIDIndex());
262 return newValue;
263
264 } else {
265 return null;
266 }
267 }
268
269 if (!oldValue.equals(newValue)) {
270 oldValue.setParent(null);
271 releaseThisandParentDOM();
272 idIndex.deregisterIDMappings(oldValue.getIDIndex());
273 if (newValue != null) {
274 newValue.setParent(this);
275 idIndex.registerIDMappings(newValue.getIDIndex());
276 }
277 }
278
279 return newValue;
280 }
281
282
283
284
285
286
287
288
289
290 protected void registerOwnID(String oldID, String newID) {
291 String newString = DatatypeHelper.safeTrimOrNullString(newID);
292
293 if (!DatatypeHelper.safeEquals(oldID, newString)) {
294 if (oldID != null) {
295 idIndex.deregisterIDMapping(oldID);
296 }
297
298 if (newString != null) {
299 idIndex.registerIDMapping(newString, this);
300 }
301 }
302 }
303
304
305 public void releaseChildrenDOM(boolean propagateRelease) {
306 log.trace("Releasing cached DOM reprsentation for children of {} with propagation set to {}",
307 getElementQName(), propagateRelease);
308 if (getOrderedChildren() != null) {
309 for (XMLObject child : getOrderedChildren()) {
310 if (child != null) {
311 child.releaseDOM();
312 if (propagateRelease) {
313 child.releaseChildrenDOM(propagateRelease);
314 }
315 }
316 }
317 }
318 }
319
320
321 public void releaseDOM() {
322 log.trace("Releasing cached DOM reprsentation for {}", getElementQName());
323 setDOM(null);
324 }
325
326
327 public void releaseParentDOM(boolean propagateRelease) {
328 log.trace("Releasing cached DOM reprsentation for parent of {} with propagation set to {}", getElementQName(),
329 propagateRelease);
330 XMLObject parentElement = getParent();
331 if (parentElement != null) {
332 parent.releaseDOM();
333 if (propagateRelease) {
334 parent.releaseParentDOM(propagateRelease);
335 }
336 }
337 }
338
339
340
341
342
343 public void releaseThisAndChildrenDOM() {
344 if (getDOM() != null) {
345 releaseDOM();
346 releaseChildrenDOM(true);
347 }
348 }
349
350
351
352
353
354 public void releaseThisandParentDOM() {
355 if (getDOM() != null) {
356 releaseDOM();
357 releaseParentDOM(true);
358 }
359 }
360
361
362 public void removeNamespace(Namespace namespace) {
363 namespaces.remove(namespace);
364 }
365
366
367 public XMLObject resolveID(String id) {
368 return idIndex.lookup(id);
369 }
370
371
372 public XMLObject resolveIDFromRoot(String id) {
373 XMLObject root = this;
374 while (root.hasParent()) {
375 root = root.getParent();
376 }
377 return root.resolveID(id);
378 }
379
380
381 public void setDOM(Element newDom) {
382 dom = newDom;
383 }
384
385
386
387
388
389
390 public void setElementNamespacePrefix(String prefix) {
391 if (prefix == null) {
392 elementQname = new QName(elementQname.getNamespaceURI(), elementQname.getLocalPart());
393 } else {
394 elementQname = new QName(elementQname.getNamespaceURI(), elementQname.getLocalPart(), prefix);
395 }
396 }
397
398
399
400
401
402
403 protected void setElementQName(QName elementQName) {
404 this.elementQname = XMLHelper.constructQName(elementQName.getNamespaceURI(), elementQName.getLocalPart(),
405 elementQName.getPrefix());
406 addNamespace(new Namespace(elementQName.getNamespaceURI(), elementQName.getLocalPart()));
407 }
408
409
410 public void setNoNamespaceSchemaLocation(String location) {
411 noNamespaceSchemaLocation = DatatypeHelper.safeTrimOrNullString(location);
412 }
413
414
415 public void setParent(XMLObject newParent) {
416 parent = newParent;
417 }
418
419
420 public void setSchemaLocation(String location) {
421 schemaLocation = DatatypeHelper.safeTrimOrNullString(location);
422 }
423
424
425
426
427
428
429
430
431 protected void setSchemaType(QName type) {
432 if (type == null) {
433 typeQname = null;
434 } else {
435 typeQname = type;
436 addNamespace(new Namespace(type.getNamespaceURI(), type.getPrefix()));
437 }
438 }
439
440 }