001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.server.schema.registries;
021    
022    
023    import java.util.ArrayList;
024    import java.util.Comparator;
025    import java.util.Iterator;
026    import java.util.List;
027    import java.util.Map;
028    import java.util.concurrent.ConcurrentHashMap;
029    
030    import javax.naming.NamingException;
031    
032    import org.apache.directory.shared.asn1.primitives.OID;
033    import org.apache.directory.shared.ldap.schema.parsers.ComparatorDescription;
034    import org.slf4j.Logger;
035    import org.slf4j.LoggerFactory;
036    
037    
038    /**
039     * A simple POJO implementation of the ComparatorRegistry service interface.
040     *
041     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042     * @version $Rev: 780471 $
043     */
044    public class DefaultComparatorRegistry implements ComparatorRegistry
045    {
046        /** static class logger */
047        private static final Logger LOG = LoggerFactory.getLogger( DefaultComparatorRegistry.class );
048        
049        /** A speedup for debug */
050        private static final boolean DEBUG = LOG.isDebugEnabled();
051    
052        /** the comparators in this registry */
053        private final Map<String,Comparator<?>> byOidComparator;
054        
055        /** maps oids to a comparator description */
056        private final Map<String, ComparatorDescription> oidToDescription;
057    
058        // ------------------------------------------------------------------------
059        // C O N S T R U C T O R S
060        // ------------------------------------------------------------------------
061    
062    
063        /**
064         * Creates a DefaultComparatorRegistry by initializing the maps
065         */
066        public DefaultComparatorRegistry()
067        {
068            byOidComparator = new ConcurrentHashMap<String, Comparator<?>>();
069            oidToDescription = new ConcurrentHashMap<String, ComparatorDescription>();
070        }
071    
072    
073        // ------------------------------------------------------------------------
074        // Service Methods
075        // ------------------------------------------------------------------------
076        /**
077         * {@inheritDoc}
078         */
079        public void register( ComparatorDescription description, Comparator<?> comparator ) throws NamingException
080        {
081            String oid = description.getNumericOid();
082            
083            if ( byOidComparator.containsKey( oid ) )
084            {
085                String msg = "Comparator '" + description + "' with OID " + oid + " already registered!";
086                LOG.warn( msg );
087                throw new NamingException( msg );
088            }
089    
090            oidToDescription.put( oid, description );
091            byOidComparator.put( oid, comparator );
092            
093            if ( DEBUG )
094            {
095                LOG.debug( "registed comparator with OID: {}", oid );
096            }
097        }
098    
099        
100        /**
101         * Return the schema, contained in the first position of the extensions
102         */
103        private static String getSchema( ComparatorDescription desc )
104        {
105            List<String> values = desc.getExtensions().get( "X-SCHEMA" );
106            
107            if ( ( values == null ) || ( values.size() == 0 ) )
108            {
109                return "other";
110            }
111            
112            return values.get( 0 );
113        }
114        
115    
116        /**
117         * {@inheritDoc}
118         */
119        public Comparator<?> lookup( String oid ) throws NamingException
120        {
121            Comparator<?> c = byOidComparator.get( oid );
122            
123            if ( c == null )
124            {
125                String msg = "Comparator not found for OID: " + oid;
126                LOG.error( msg );
127                throw new NamingException( msg );
128            }
129            
130            if ( DEBUG )
131            {
132                LOG.debug( "looked up comparator with OID: {}", oid );
133            }
134            
135            return c;
136        }
137    
138    
139        /**
140         * {@inheritDoc}
141         */
142        public boolean hasComparator( String oid )
143        {
144            return byOidComparator.containsKey( oid );
145        }
146    
147    
148        /**
149         * {@inheritDoc}
150         */
151        public String getSchemaName( String oid ) throws NamingException
152        {
153            if ( ! OID.isOID( oid ) )
154            {
155                String msg = "OID " + oid + " is not a numeric OID";
156                LOG.error( msg );
157                throw new NamingException( msg );
158            }
159    
160            ComparatorDescription description = oidToDescription.get( oid );
161            
162            if ( description != null )
163            {
164                return getSchema( description );
165            }
166    
167            String msg = "OID " + oid + " not found in oid to description map!";
168            LOG.error( msg );
169            throw new NamingException( msg );
170        }
171    
172    
173        /**
174         * {@inheritDoc}
175         */
176        public Iterator<String> iterator()
177        {
178            return byOidComparator.keySet().iterator();
179        }
180    
181    
182        /**
183         * {@inheritDoc}
184         */
185        public void unregister( String oid ) throws NamingException
186        {
187            if ( ! OID.isOID( oid ) )
188            {
189                String msg = "OID " + oid + " is not a numeric OID";
190                LOG.error( msg );
191                throw new NamingException( msg );
192            }
193    
194            byOidComparator.remove( oid );
195            oidToDescription.remove( oid );
196        }
197        
198        
199        /**
200         * {@inheritDoc}
201         */
202        public void unregisterSchemaElements( String schemaName )
203        {
204            List<String> oids = new ArrayList<String>( byOidComparator.keySet() );
205            
206            for ( String oid : oids )
207            {
208                ComparatorDescription description = oidToDescription.get( oid );
209                String schemaNameForOid = getSchema( description );
210                
211                if ( schemaNameForOid.equalsIgnoreCase( schemaName ) )
212                {
213                    byOidComparator.remove( oid );
214                    oidToDescription.remove( oid );
215                }
216            }
217        }
218    
219    
220        /**
221         * {@inheritDoc}
222         */
223        public void renameSchema( String originalSchemaName, String newSchemaName )
224        {
225            List<String> oids = new ArrayList<String>( byOidComparator.keySet() );
226            
227            for ( String oid : oids )
228            {
229                ComparatorDescription description = oidToDescription.get( oid );
230                String schemaNameForOid = getSchema( description );
231                
232                if ( schemaNameForOid.equalsIgnoreCase( originalSchemaName ) )
233                {
234                    List<String> schemaExt = description.getExtensions().get( "X-SCHEMA" );
235                    schemaExt.clear();
236                    schemaExt.add( newSchemaName );
237                }
238            }
239        }
240    
241    
242        /**
243         * {@inheritDoc}
244         */
245        public Iterator<ComparatorDescription> comparatorDescriptionIterator()
246        {
247            return oidToDescription.values().iterator();
248        }
249    }