1 /*
2 * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.opensaml.xml.util;
18
19 import java.util.Collections;
20 import java.util.Map;
21 import java.util.Set;
22
23 import net.jcip.annotations.NotThreadSafe;
24
25 import org.opensaml.xml.XMLObject;
26
27 /**
28 * Class which provides storage for the ID-to-XMLObject index mapping on an owning {@link org.opensaml.xml.XMLObject}.
29 */
30 @NotThreadSafe
31 public class IDIndex {
32
33 /** The XMLObject which owns this ID index. */
34 private XMLObject owner;
35
36 /** Mapping of ID attributes to XMLObjects in the subtree rooted at this object's owner.
37 * This allows constant-time dereferencing of ID-typed attributes within the subtree. */
38 private Map<String, XMLObject> idMappings;
39
40 /**
41 * Constructor.
42 *
43 * @param newOwner the XMLObject which owns this ID-to-XMLObject index
44 *
45 * @throws NullPointerException thrown if the given XMLObject is null
46 */
47 public IDIndex(XMLObject newOwner) throws NullPointerException {
48 if (newOwner == null) {
49 throw new NullPointerException("Attribute owner XMLObject may not be null");
50 }
51
52 owner = newOwner;
53 idMappings = new LazyMap<String, XMLObject>();
54 }
55
56
57 /**
58 * Register an ID-to-XMLObject mapping for one of this object's owner's children.
59 *
60 * @param id the XMLObject child's ID attribute value
61 * @param referent the XMLObject child
62 */
63 public void registerIDMapping(String id, XMLObject referent) {
64 if (id == null) {
65 return;
66 }
67
68 idMappings.put(id, referent);
69 if (owner.hasParent()) {
70 owner.getParent().getIDIndex().registerIDMapping(id, referent);
71 }
72 }
73
74 /**
75 * Register multiple ID-to-XMLObject mappings for this object's owner's children.
76 *
77 * @param idIndex the ID-to-XMLObject mapping to register
78 */
79 public void registerIDMappings(IDIndex idIndex) {
80 if (idIndex == null || idIndex.isEmpty()) {
81 return;
82 }
83
84 idMappings.putAll(idIndex.getIDMappings());
85 if (owner.hasParent()) {
86 owner.getParent().getIDIndex().registerIDMappings(idIndex);
87 }
88 }
89
90 /**
91 * Deregister an ID-to-XMLObject mapping for one of this object's owner's children.
92 *
93 * @param id the ID attribute value of the XMLObject child to deregister
94 */
95 public void deregisterIDMapping(String id) {
96 if (id == null) {
97 return;
98 }
99
100 idMappings.remove(id);
101 if (owner.hasParent()) {
102 owner.getParent().getIDIndex().deregisterIDMapping(id);
103 }
104 }
105
106 /**
107 * Deregister multiple ID-to-XMLObject mappings for this object's owner's children.
108 *
109 * @param idIndex the ID-to-XMLObject mappings to deregister
110 */
111 public void deregisterIDMappings(IDIndex idIndex) {
112 if (idIndex == null || idIndex.isEmpty()) {
113 return;
114 }
115
116 for (String id : idIndex.getIDs()) {
117 idMappings.remove(id);
118 }
119 if (owner.hasParent()) {
120 owner.getParent().getIDIndex().deregisterIDMappings(idIndex);
121 }
122 }
123
124 /**
125 * Lookup and return the XMLObject identified by the specified ID attribute.
126 *
127 * @param id the ID attribute value to lookup
128 * @return the XMLObject identified by the ID attribute value
129 */
130 public XMLObject lookup(String id) {
131 return idMappings.get(id);
132 }
133
134 /**
135 * Return whether the index is currently empty.
136 *
137 * @return true if the index is currently empty
138 */
139 public boolean isEmpty() {
140 return idMappings.isEmpty();
141 }
142
143 /**
144 * Get the set of ID strings which are the index keys.
145 *
146 * @return the set of ID strings which are keys to the index
147 */
148 public Set<String> getIDs() {
149 return Collections.unmodifiableSet(idMappings.keySet());
150 }
151
152 /**
153 * Get the ID-to-XMLObject mappings for this object's object's owner's children.
154 *
155 * @return the ID-to-XMLObject mapping
156 */
157 protected Map<String, XMLObject> getIDMappings() {
158 return Collections.unmodifiableMap(idMappings);
159 }
160
161 }