View Javadoc

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  import java.util.concurrent.ConcurrentHashMap;
23  
24  import org.opensaml.xml.XMLObject;
25  
26  /**
27   * Class which provides storage for the ID-to-XMLObject index mapping on an owning {@link org.opensaml.xml.XMLObject}.
28   */
29  public class IDIndex {
30      
31      /** The XMLObject which owns this ID index. */
32      private XMLObject owner;
33      
34      /** Mapping of ID attributes to XMLObjects in the subtree rooted at this object's owner.
35       * This allows constant-time dereferencing of ID-typed attributes within the subtree.  */
36      private Map<String, XMLObject> idMappings;
37  
38      /**
39       * Constructor.
40       *
41       * @param newOwner the XMLObject which owns this ID-to-XMLObject index
42       * 
43       * @throws NullPointerException thrown if the given XMLObject is null
44       */
45      public IDIndex(XMLObject newOwner) throws NullPointerException {
46          if (newOwner == null) {
47              throw new NullPointerException("Attribute owner XMLObject may not be null");
48          }
49          
50          owner = newOwner;
51          idMappings = new ConcurrentHashMap<String, XMLObject>();
52      }
53      
54  
55      /**
56       * Register an ID-to-XMLObject mapping for one of this object's owner's children.
57       * 
58       * @param id the XMLObject child's ID attribute value
59       * @param referent the XMLObject child
60       */
61      public void registerIDMapping(String id, XMLObject referent) {
62          if (id == null) {
63              return;
64          }
65          
66          idMappings.put(id, referent);
67          if (owner.hasParent()) {
68              owner.getParent().getIDIndex().registerIDMapping(id, referent);
69          }
70      }
71      
72      /**
73       * Register multiple ID-to-XMLObject mappings for this object's owner's children.
74       * 
75       * @param idIndex the ID-to-XMLObject mapping to register
76       */
77      public void registerIDMappings(IDIndex idIndex) {
78          if (idIndex == null || idIndex.isEmpty()) {
79              return;
80          }
81          
82          idMappings.putAll(idIndex.getIDMappings());
83          if (owner.hasParent()) {
84              owner.getParent().getIDIndex().registerIDMappings(idIndex);
85          }
86      }
87      
88      /**
89       * Deregister an ID-to-XMLObject mapping for one of this object's owner's children.
90       * 
91       * @param id the ID attribute value of the XMLObject child to deregister
92       */  
93      public void deregisterIDMapping(String id) {
94          if (id == null) {
95              return;
96          }
97          
98          idMappings.remove(id);
99          if (owner.hasParent()) {
100             owner.getParent().getIDIndex().deregisterIDMapping(id);
101         }
102     }
103     
104     /**
105      * Deregister multiple ID-to-XMLObject mappings for this object's owner's children.
106      * 
107      * @param idIndex the ID-to-XMLObject mappings to deregister
108      */
109     public void deregisterIDMappings(IDIndex idIndex) {
110         if (idIndex == null || idIndex.isEmpty()) {
111             return;
112         }
113         
114         for (String id : idIndex.getIDs()) {
115             idMappings.remove(id);
116         }
117         if (owner.hasParent()) {
118             owner.getParent().getIDIndex().deregisterIDMappings(idIndex);
119         }
120     }
121  
122     /**
123      * Lookup and return the XMLObject identified by the specified ID attribute.
124      * 
125      * @param id the ID attribute value to lookup
126      * @return the XMLObject identified by the ID attribute value
127      */
128     public XMLObject lookup(String id) {
129         return idMappings.get(id);
130     }
131     
132     /**
133      * Return whether the index is currently empty.
134      * 
135      * @return true if the index is currently empty
136      */
137     public boolean isEmpty() {
138         return idMappings.isEmpty();
139     }
140     
141     /**
142      * Get the set of ID strings which are the index keys.
143      * 
144      * @return the set of ID strings which are keys to the index
145      */
146     public Set<String> getIDs() {
147         return Collections.unmodifiableSet(idMappings.keySet());
148     }
149     
150     /**
151      * Get the ID-to-XMLObject mappings for this object's object's owner's children.
152      * 
153      * @return the ID-to-XMLObject mapping
154      */
155     protected Map<String, XMLObject> getIDMappings() {
156         return Collections.unmodifiableMap(idMappings);
157     }
158     
159 }