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