001    /*
002     * JBoss, Home of Professional Open Source.
003     * Copyright 2008, Red Hat Middleware LLC, and individual contributors
004     * as indicated by the @author tags. See the copyright.txt file in the
005     * distribution for a full listing of individual contributors. 
006     *
007     * This is free software; you can redistribute it and/or modify it
008     * under the terms of the GNU Lesser General Public License as
009     * published by the Free Software Foundation; either version 2.1 of
010     * the License, or (at your option) any later version.
011     *
012     * This software is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * Lesser General Public License for more details.
016     *
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this software; if not, write to the Free
019     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021     */
022    package org.jboss.dna.graph.properties.basic;
023    
024    import java.util.Collections;
025    import java.util.HashMap;
026    import java.util.HashSet;
027    import java.util.Map;
028    import java.util.Set;
029    import net.jcip.annotations.ThreadSafe;
030    import org.jboss.dna.common.util.CheckArg;
031    import org.jboss.dna.graph.properties.NamespaceRegistry;
032    
033    /**
034     * @author Randall Hauch
035     */
036    @ThreadSafe
037    public class LocalNamespaceRegistry extends BasicNamespaceRegistry {
038    
039        private final NamespaceRegistry delegate;
040    
041        /**
042         * @param delegate the namespace registry that this registry should delegate to if not found locally
043         */
044        public LocalNamespaceRegistry( NamespaceRegistry delegate ) {
045            super();
046            CheckArg.isNotNull(delegate, "delegate");
047            this.delegate = delegate;
048            unregister(DEFAULT_NAMESPACE_URI);
049        }
050    
051        /**
052         * @param delegate the namespace registry that this registry should delegate to if not found locally
053         * @param defaultNamespaceUri the namespace URI to use for the default prefix
054         */
055        public LocalNamespaceRegistry( NamespaceRegistry delegate,
056                                       final String defaultNamespaceUri ) {
057            super();
058            CheckArg.isNotNull(delegate, "delegate");
059            this.delegate = delegate;
060            register("", defaultNamespaceUri);
061        }
062    
063        /**
064         * {@inheritDoc}
065         * 
066         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getDefaultNamespaceUri()
067         */
068        @Override
069        public String getDefaultNamespaceUri() {
070            String result = super.getDefaultNamespaceUri();
071            if (result == null) result = this.delegate.getDefaultNamespaceUri();
072            return result;
073        }
074    
075        /**
076         * {@inheritDoc}
077         * 
078         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getNamespaceForPrefix(java.lang.String)
079         */
080        @Override
081        public String getNamespaceForPrefix( String prefix ) {
082            String result = super.getNamespaceForPrefix(prefix);
083            if (result == null) result = this.delegate.getNamespaceForPrefix(prefix);
084            return result;
085        }
086    
087        /**
088         * {@inheritDoc}
089         * 
090         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getNamespaces()
091         */
092        @Override
093        public Set<Namespace> getNamespaces() {
094            Set<Namespace> delegateNamespaces = this.delegate.getNamespaces();
095            Set<Namespace> localNamespaces = super.getNamespaces();
096    
097            // Load the local namespaces first ...
098            Set<Namespace> namespaces = new HashSet<Namespace>(localNamespaces);
099    
100            // Now build a map of the local prefixes so we can check for prefixes
101            Map<String, Namespace> localNamespacesByPrefix = new HashMap<String, Namespace>();
102            for (Namespace ns : localNamespaces)
103                localNamespacesByPrefix.put(ns.getPrefix(), ns);
104    
105            // Now iterate over the local namespaces, removing any existing namespace with the same prefix
106            for (Namespace ns : delegateNamespaces) {
107                if (localNamespacesByPrefix.get(ns.getPrefix()) != null) continue;
108                // Try to add the delegate namespace, which won't work if a local with the same URI was already added...
109                namespaces.add(ns);
110            }
111            return Collections.unmodifiableSet(namespaces);
112        }
113    
114        /**
115         * {@inheritDoc}
116         * 
117         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getPrefixForNamespaceUri(java.lang.String, boolean)
118         */
119        @Override
120        public String getPrefixForNamespaceUri( String namespaceUri,
121                                                boolean generateIfMissing ) {
122            String result = super.getPrefixForNamespaceUri(namespaceUri, false);
123            if (result == null) result = this.delegate.getPrefixForNamespaceUri(namespaceUri, false);
124            if (result == null && generateIfMissing) result = super.getPrefixForNamespaceUri(namespaceUri, true);
125            return result;
126        }
127    
128        /**
129         * {@inheritDoc}
130         * 
131         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#getRegisteredNamespaceUris()
132         */
133        @Override
134        public Set<String> getRegisteredNamespaceUris() {
135            Set<String> uris = new HashSet<String>(this.delegate.getRegisteredNamespaceUris());
136            uris.addAll(super.getRegisteredNamespaceUris());
137            return Collections.unmodifiableSet(uris);
138        }
139    
140        /**
141         * {@inheritDoc}
142         * 
143         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#isRegisteredNamespaceUri(java.lang.String)
144         */
145        @Override
146        public boolean isRegisteredNamespaceUri( String namespaceUri ) {
147            return super.isRegisteredNamespaceUri(namespaceUri) || this.delegate.isRegisteredNamespaceUri(namespaceUri);
148        }
149    
150        /**
151         * {@inheritDoc}
152         * 
153         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#register(java.lang.String, java.lang.String)
154         */
155        @Override
156        public String register( String prefix,
157                                String namespaceUri ) {
158            // Just register the namespace locally ...
159            String previous = super.register(prefix, namespaceUri);
160            // But check whether there is a "previous" from the delegate ...
161            if (previous == null && delegate != null) previous = delegate.getPrefixForNamespaceUri(namespaceUri, false);
162            return previous;
163        }
164    
165        /**
166         * {@inheritDoc}
167         * 
168         * @see org.jboss.dna.graph.properties.basic.BasicNamespaceRegistry#unregister(java.lang.String)
169         */
170        @Override
171        public boolean unregister( String namespaceUri ) {
172            // Unregister locally ...
173            return super.unregister(namespaceUri);
174        }
175    
176    }