View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.property.basic;
25  
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.Map;
30  import java.util.Set;
31  import net.jcip.annotations.ThreadSafe;
32  import org.modeshape.common.util.CheckArg;
33  import org.modeshape.graph.property.NamespaceRegistry;
34  
35  /**
36   * A special {@link NamespaceRegistry} implementation that can be used to track transient registrations for another delegate
37   * registry.
38   */
39  @ThreadSafe
40  public class LocalNamespaceRegistry extends SimpleNamespaceRegistry {
41  
42      private final NamespaceRegistry delegate;
43  
44      /**
45       * @param delegate the namespace registry that this registry should delegate to if not found locally
46       */
47      public LocalNamespaceRegistry( NamespaceRegistry delegate ) {
48          super();
49          CheckArg.isNotNull(delegate, "delegate");
50          this.delegate = delegate;
51          unregister(DEFAULT_NAMESPACE_URI);
52      }
53  
54      /**
55       * @param delegate the namespace registry that this registry should delegate to if not found locally
56       * @param defaultNamespaceUri the namespace URI to use for the default prefix
57       */
58      public LocalNamespaceRegistry( NamespaceRegistry delegate,
59                                     final String defaultNamespaceUri ) {
60          super();
61          CheckArg.isNotNull(delegate, "delegate");
62          this.delegate = delegate;
63          register("", defaultNamespaceUri);
64      }
65  
66      /**
67       * {@inheritDoc}
68       * 
69       * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#getDefaultNamespaceUri()
70       */
71      @Override
72      public String getDefaultNamespaceUri() {
73          String result = super.getDefaultNamespaceUri();
74          if (result == null) result = this.delegate.getDefaultNamespaceUri();
75          return result;
76      }
77  
78      /**
79       * {@inheritDoc}
80       * 
81       * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#getNamespaceForPrefix(java.lang.String)
82       */
83      @Override
84      public String getNamespaceForPrefix( String prefix ) {
85          String result = super.getNamespaceForPrefix(prefix);
86          if (result == null) {
87              result = this.delegate.getNamespaceForPrefix(prefix);
88              // Catch if this namespace was remapped
89              if (result != null && super.getPrefixForNamespaceUri(result, false) != null) {
90                  return null;
91              }
92          }
93          return result;
94      }
95  
96      /**
97       * {@inheritDoc}
98       * 
99       * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#getNamespaces()
100      */
101     @Override
102     public Set<Namespace> getNamespaces() {
103         Set<Namespace> delegateNamespaces = this.delegate.getNamespaces();
104         Set<Namespace> localNamespaces = super.getNamespaces();
105         if (localNamespaces.isEmpty()) return delegateNamespaces;
106 
107         // Load the local namespaces first ...
108         Set<Namespace> namespaces = new HashSet<Namespace>(localNamespaces);
109 
110         // Now build a map of the local prefixes so we can check for prefixes
111         Map<String, Namespace> localNamespacesByPrefix = new HashMap<String, Namespace>();
112         for (Namespace ns : localNamespaces)
113             localNamespacesByPrefix.put(ns.getPrefix(), ns);
114 
115         // Now iterate over the local namespaces, removing any existing namespace with the same prefix
116         for (Namespace ns : delegateNamespaces) {
117             if (localNamespacesByPrefix.get(ns.getPrefix()) != null) continue;
118             // Try to add the delegate namespace, which won't work if a local with the same URI was already added...
119             namespaces.add(ns);
120         }
121         return Collections.unmodifiableSet(namespaces);
122     }
123 
124     /**
125      * Obtain the set of namespaces that are overridden within this {@link LocalNamespaceRegistry} instance.
126      * 
127      * @return the set of overridden namespace mappings; never null but possibly empty
128      */
129     public Set<Namespace> getLocalNamespaces() {
130         return super.getNamespaces();
131     }
132 
133     /**
134      * {@inheritDoc}
135      * 
136      * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#getPrefixForNamespaceUri(java.lang.String, boolean)
137      */
138     @Override
139     public String getPrefixForNamespaceUri( String namespaceUri,
140                                             boolean generateIfMissing ) {
141         String result = super.getPrefixForNamespaceUri(namespaceUri, false);
142         if (result == null) {
143             result = this.delegate.getPrefixForNamespaceUri(namespaceUri, false);
144             if (result != null) {
145                 // This was remapped at the session layer
146                 if (!this.getNamespaceForPrefix(result).equals(namespaceUri)) {
147                     result = null;
148                 }
149             }
150         }
151         if (result == null && generateIfMissing) result = super.getPrefixForNamespaceUri(namespaceUri, true);
152         return result;
153     }
154 
155     /**
156      * {@inheritDoc}
157      * 
158      * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#getRegisteredNamespaceUris()
159      */
160     @Override
161     public Set<String> getRegisteredNamespaceUris() {
162         Set<String> uris = new HashSet<String>(this.delegate.getRegisteredNamespaceUris());
163         uris.addAll(super.getRegisteredNamespaceUris());
164         return Collections.unmodifiableSet(uris);
165     }
166 
167     /**
168      * {@inheritDoc}
169      * 
170      * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#isRegisteredNamespaceUri(java.lang.String)
171      */
172     @Override
173     public boolean isRegisteredNamespaceUri( String namespaceUri ) {
174         return super.isRegisteredNamespaceUri(namespaceUri) || this.delegate.isRegisteredNamespaceUri(namespaceUri);
175     }
176 
177     /**
178      * {@inheritDoc}
179      * 
180      * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#register(java.lang.String, java.lang.String)
181      */
182     @Override
183     public String register( String prefix,
184                             String namespaceUri ) {
185         // Just register the namespace locally ...
186         String previous = super.register(prefix, namespaceUri);
187         // But check whether there is a "previous" from the delegate ...
188         if (previous == null && delegate != null) previous = delegate.getPrefixForNamespaceUri(namespaceUri, false);
189         return previous;
190     }
191 
192     /**
193      * {@inheritDoc}
194      * 
195      * @see org.modeshape.graph.property.basic.SimpleNamespaceRegistry#unregister(java.lang.String)
196      */
197     @Override
198     public boolean unregister( String namespaceUri ) {
199         // Unregister locally ...
200         return super.unregister(namespaceUri);
201     }
202 
203 }