/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.directory.shared.ldap.schema.registries;


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.directory.shared.i18n.I18n;
import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
import org.apache.directory.shared.ldap.exception.LdapException;
import org.apache.directory.shared.ldap.exception.LdapProtocolErrorException;
import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
import org.apache.directory.shared.ldap.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.DITContentRule;
import org.apache.directory.shared.ldap.schema.DITStructureRule;
import org.apache.directory.shared.ldap.schema.LdapComparator;
import org.apache.directory.shared.ldap.schema.LdapSyntax;
import org.apache.directory.shared.ldap.schema.LoadableSchemaObject;
import org.apache.directory.shared.ldap.schema.MatchingRule;
import org.apache.directory.shared.ldap.schema.MatchingRuleUse;
import org.apache.directory.shared.ldap.schema.NameForm;
import org.apache.directory.shared.ldap.schema.Normalizer;
import org.apache.directory.shared.ldap.schema.ObjectClass;
import org.apache.directory.shared.ldap.schema.SchemaManager;
import org.apache.directory.shared.ldap.schema.SchemaObject;
import org.apache.directory.shared.ldap.schema.SchemaObjectWrapper;
import org.apache.directory.shared.ldap.schema.SyntaxChecker;
import org.apache.directory.shared.ldap.util.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Document this class.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class Registries implements SchemaLoaderListener, Cloneable
{
    /** A logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( Registries.class );

    /**
     * A String name to Schema object map for the schemas loaded into this
     * registry. The loaded schemas may be disabled.
     */
    protected Map<String, Schema> loadedSchemas = new HashMap<String, Schema>();

    /** The AttributeType registry */
    protected AttributeTypeRegistry attributeTypeRegistry;

    /** The ObjectClass registry */
    protected ObjectClassRegistry objectClassRegistry;

    /** The LdapSyntax registry */
    protected ComparatorRegistry comparatorRegistry;

    /** The DitContentRule registry */
    protected DITContentRuleRegistry ditContentRuleRegistry;

    /** The DitStructureRule registry */
    protected DITStructureRuleRegistry ditStructureRuleRegistry;

    /** The MatchingRule registry */
    protected MatchingRuleRegistry matchingRuleRegistry;

    /** The MatchingRuleUse registry */
    protected MatchingRuleUseRegistry matchingRuleUseRegistry;

    /** The NameForm registry */
    protected NameFormRegistry nameFormRegistry;

    /** The Normalizer registry */
    protected NormalizerRegistry normalizerRegistry;

    /** The global OID registry */
    protected OidRegistry globalOidRegistry;

    /** The SyntaxChecker registry */
    protected SyntaxCheckerRegistry syntaxCheckerRegistry;

    /** The LdapSyntax registry */
    protected LdapSyntaxRegistry ldapSyntaxRegistry;

    /** A map storing all the schema objects associated with a schema */
    private Map<String, Set<SchemaObjectWrapper>> schemaObjects;

    /** A flag indicating that the Registries is relaxed or not */
    private boolean isRelaxed;

    /** A flag indicating that disabled SchemaObject are accepted */
    private boolean disabledAccepted;

    /** Two flags for RELAXED and STRUCT */
    public static final boolean STRICT = false;
    public static final boolean RELAXED = true;

    /**
     *  A map storing a relation between a SchemaObject and all the 
     *  referencing SchemaObjects.
     */
    protected Map<SchemaObjectWrapper, Set<SchemaObjectWrapper>> usedBy;

    /**
     *  A map storing a relation between a SchemaObject and all the 
     *  SchemaObjects it uses.
     */
    protected Map<SchemaObjectWrapper, Set<SchemaObjectWrapper>> using;

    /** A reference on the schema Manager */
    @SuppressWarnings("PMD.UnusedPrivateField")
    // False positive 
    private SchemaManager schemaManager;


    /**
     * Creates a new instance of Registries.
     *
     * @param schemaManager the schema manager
     */
    public Registries( SchemaManager schemaManager )
    {
        this.globalOidRegistry = new OidRegistry();
        attributeTypeRegistry = new DefaultAttributeTypeRegistry();
        comparatorRegistry = new DefaultComparatorRegistry();
        ditContentRuleRegistry = new DefaultDITContentRuleRegistry();
        ditStructureRuleRegistry = new DefaultDITStructureRuleRegistry();
        ldapSyntaxRegistry = new DefaultLdapSyntaxRegistry();
        matchingRuleRegistry = new DefaultMatchingRuleRegistry();
        matchingRuleUseRegistry = new DefaultMatchingRuleUseRegistry();
        nameFormRegistry = new DefaultNameFormRegistry();
        normalizerRegistry = new DefaultNormalizerRegistry();
        objectClassRegistry = new DefaultObjectClassRegistry();
        syntaxCheckerRegistry = new DefaultSyntaxCheckerRegistry();
        schemaObjects = new HashMap<String, Set<SchemaObjectWrapper>>();
        usedBy = new HashMap<SchemaObjectWrapper, Set<SchemaObjectWrapper>>();
        using = new HashMap<SchemaObjectWrapper, Set<SchemaObjectWrapper>>();

        isRelaxed = STRICT;
        disabledAccepted = false;
        this.schemaManager = schemaManager;
    }


    /**
     * @return The AttributeType registry
     */
    public AttributeTypeRegistry getAttributeTypeRegistry()
    {
        return attributeTypeRegistry;
    }


    /**
     * @return The Comparator registry
     */
    public ComparatorRegistry getComparatorRegistry()
    {
        return comparatorRegistry;
    }


    /**
     * @return The DITContentRule registry
     */
    public DITContentRuleRegistry getDitContentRuleRegistry()
    {
        return ditContentRuleRegistry;
    }


    /**
     * @return The DITStructureRule registry
     */
    public DITStructureRuleRegistry getDitStructureRuleRegistry()
    {
        return ditStructureRuleRegistry;
    }


    /**
     * @return The MatchingRule registry
     */
    public MatchingRuleRegistry getMatchingRuleRegistry()
    {
        return matchingRuleRegistry;
    }


    /**
     * @return The MatchingRuleUse registry
     */
    public MatchingRuleUseRegistry getMatchingRuleUseRegistry()
    {
        return matchingRuleUseRegistry;
    }


    /**
     * @return The NameForm registry
     */
    public NameFormRegistry getNameFormRegistry()
    {
        return nameFormRegistry;
    }


    /**
     * @return The Normalizer registry
     */
    public NormalizerRegistry getNormalizerRegistry()
    {
        return normalizerRegistry;
    }


    /**
     * @return The ObjectClass registry
     */
    public ObjectClassRegistry getObjectClassRegistry()
    {
        return objectClassRegistry;
    }


    /**
     * @return The global Oid registry
     */
    public OidRegistry getGlobalOidRegistry()
    {
        return globalOidRegistry;
    }


    /**
     * @return The SyntaxChecker registry
     */
    public SyntaxCheckerRegistry getSyntaxCheckerRegistry()
    {
        return syntaxCheckerRegistry;
    }


    /**
     * @return The LdapSyntax registry
     */
    public LdapSyntaxRegistry getLdapSyntaxRegistry()
    {
        return ldapSyntaxRegistry;
    }


    /**
     * Get an OID from a name. As we have many possible registries, we 
     * have to look in all of them to get the one containing the OID.
     *
     * @param name The name we are looking at
     * @return The associated OID
     */
    // This will suppress PMD.EmptyCatchBlock warnings in this method
    @SuppressWarnings("PMD.EmptyCatchBlock")
    public String getOid( String name )
    {
        // we have many possible Registries to look at.
        // AttributeType
        try
        {
            AttributeType attributeType = attributeTypeRegistry.lookup( name );

            if ( attributeType != null )
            {
                return attributeType.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // ObjectClass
        try
        {
            ObjectClass objectClass = objectClassRegistry.lookup( name );

            if ( objectClass != null )
            {
                return objectClass.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // LdapSyntax
        try
        {
            LdapSyntax ldapSyntax = ldapSyntaxRegistry.lookup( name );

            if ( ldapSyntax != null )
            {
                return ldapSyntax.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // MatchingRule
        try
        {
            MatchingRule matchingRule = matchingRuleRegistry.lookup( name );

            if ( matchingRule != null )
            {
                return matchingRule.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // MatchingRuleUse
        try
        {
            MatchingRuleUse matchingRuleUse = matchingRuleUseRegistry.lookup( name );

            if ( matchingRuleUse != null )
            {
                return matchingRuleUse.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // NameForm
        try
        {
            NameForm nameForm = nameFormRegistry.lookup( name );

            if ( nameForm != null )
            {
                return nameForm.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // DITContentRule
        try
        {
            DITContentRule ditContentRule = ditContentRuleRegistry.lookup( name );

            if ( ditContentRule != null )
            {
                return ditContentRule.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // Fall down to the next registry
        }

        // DITStructureRule
        try
        {
            DITStructureRule ditStructureRule = ditStructureRuleRegistry.lookup( name );

            if ( ditStructureRule != null )
            {
                return ditStructureRule.getOid();
            }
        }
        catch ( LdapException ne )
        {
            // No more registries to look at...
        }

        return null;
    }


    /**
     * Gets a schema that has been loaded into these Registries.
     * 
     * @param schemaName the name of the schema to lookup
     * @return the loaded Schema if one corresponding to the name exists
     */
    public Schema getLoadedSchema( String schemaName )
    {
        return loadedSchemas.get( StringTools.toLowerCase( schemaName ) );
    }


    /**
     * Checks to see if a particular Schema is loaded.
     *
     * @param schemaName the name of the Schema to check
     * @return true if the Schema is loaded, false otherwise
     */
    public boolean isSchemaLoaded( String schemaName )
    {
        return loadedSchemas.containsKey( StringTools.toLowerCase( schemaName ) );
    }


    // ------------------------------------------------------------------------
    // Code used to sanity check the resolution of entities in registries
    // ------------------------------------------------------------------------
    /**
     * Attempts to resolve the dependent schema objects of all entities that
     * refer to other objects within the registries.  Null references will be
     * handed appropriately.
     * The order in which the SchemaObjects must be :
     * <li/>1) Normalizers, Comparators and SyntaxCheckers (as they depend on nothing)
     * <li/>2) Syntaxes (depend on SyntaxCheckers)
     * <li/>3) MatchingRules (depend on Syntaxes, Normalizers and Comparators
     * <li/>4) AttributeTypes (depend on MatchingRules, Syntaxes and AttributeTypes : in this case, we first handle the superior)
     * <li/>5) ObjectClasses (depend on AttributeTypes and ObjectClasses)
     * <br/><br/>
     * Later, when we will support them :
     * <li/>6) MatchingRuleUses (depend on matchingRules and AttributeTypes)
     * <li/>7) DitContentRules (depend on ObjectClasses and AttributeTypes)
     * <li/>8) NameForms (depends on ObjectClasses and AttributeTypes)
     * <li/>9) DitStructureRules (depends onNameForms and DitStructureRules)      * 
     *
     * @return a list of exceptions encountered while resolving entities
     */
    public List<Throwable> checkRefInteg()
    {
        ArrayList<Throwable> errors = new ArrayList<Throwable>();

        // Step 1 :
        // We start with Normalizers, Comparators and SyntaxCheckers
        // as they depend on nothing
        // Check the Normalizers
        for ( Normalizer normalizer : normalizerRegistry )
        {
            resolve( normalizer, errors );
        }

        // Check the Comparators
        for ( LdapComparator<?> comparator : comparatorRegistry )
        {
            resolve( comparator, errors );
        }

        // Check the SyntaxCheckers
        for ( SyntaxChecker syntaxChecker : syntaxCheckerRegistry )
        {
            resolve( syntaxChecker, errors );
        }

        // Step 2 :
        // Check the LdapSyntaxes
        for ( LdapSyntax ldapSyntax : ldapSyntaxRegistry )
        {
            resolve( ldapSyntax, errors );
        }

        // Step 3 :
        // Check the matchingRules
        for ( MatchingRule matchingRule : matchingRuleRegistry )
        {
            resolve( matchingRule, errors );
        }

        // Step 4 :
        // Check the AttributeTypes
        for ( AttributeType attributeType : attributeTypeRegistry )
        {
            resolve( attributeType, errors );
        }

        //  Step 5 :
        // Check the ObjectClasses
        for ( ObjectClass objectClass : objectClassRegistry )
        {
            resolve( objectClass, errors );
        }

        // Step 6-9 aren't yet defined
        return errors;
    }


    /**
     * Add the SchemaObjectReferences. This method does nothing, it's just
     * a catch all. The other methods will be called for each specific 
     * schemaObject
     *
    public void addCrossReferences( SchemaObject schemaObject )
    {
        // Do nothing : it's a catch all method.
    }
    
    
    /**
     * Delete the AT references (using and usedBy) : 
     * AT -> MR (for EQUALITY, ORDERING and SUBSTR)
     * AT -> S
     * AT -> AT
     */
    public void delCrossReferences( AttributeType attributeType )
    {
        if ( attributeType.getEquality() != null )
        {
            delReference( attributeType, attributeType.getEquality() );
        }

        if ( attributeType.getOrdering() != null )
        {
            delReference( attributeType, attributeType.getOrdering() );
        }

        if ( attributeType.getSubstring() != null )
        {
            delReference( attributeType, attributeType.getSubstring() );
        }

        if ( attributeType.getSyntax() != null )
        {
            delReference( attributeType, attributeType.getSyntax() );
        }

        if ( attributeType.getSuperior() != null )
        {
            delReference( attributeType, attributeType.getSuperior() );
        }
    }


    /**
     * Some specific controls must be checked : 
     * - an AT must have either a SYNTAX or a SUP. If there is no SYNTAX, then
     * the AT will take it's superior SYNTAX;
     * - if there is no EQUALITY, ORDERING or SUBSTRING MR, and if there is 
     * a SUP, then the AT will use its parent MR, if any;
     * - if an AT has a superior, then its usage must be the same than its
     * superior Usage;
     * - if an AT is COLLECTIVE, then its usage must be userApplications;
     * - if an AT is NO-USER-MODIFICATION, then its usage must be one of
     * directoryOperation, distributedOperation or dSAOperation;
     * - if an AT has a superior, and if its superior is COLLECTIVE, then
     * the AT will be COLLECTIVE too
     * 
     *
    private void buildRecursiveAttributeTypeReferences( List<Throwable> errors, Set<String> done, AttributeType attributeType )
    {
        buildReference( errors, attributeType );
        // An attributeType has references on Syntax, MatchingRule and itself
        try
        {
            attributeType.addToRegistries( this );
        }
        catch ( LdapException ne )
        {
            String msg = "Cannot build the AttributeType references for the object " + attributeType.getName() +
                ", error : " + ne.getMessage();
            
            Throwable error = new LdapSchemaViolationException( 
                msg, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX );
            errors.add( error );
            LOG.info( msg );
        }
        
        // First, check if the AT has a superior
        //buildSuperior( errors, done, attributeType );
        
        // The LdapSyntax (cannot be null)
        //buildSyntax( errors, attributeType );
        
        // The equality MR. 
        //buildEquality( errors, attributeType );

        // The ORDERING MR.
        //buildOrdering( errors, attributeType );
        
        // The SUBSTR MR.
        //buildSubstring( errors, attributeType );
        
        // Last, not least, check some of the other constraints
        //checkUsage( errors, attributeType );
        //checkCollective( errors, attributeType );
        
        // Update the dedicated fields
        /*try
        {
            attributeTypeRegistry.addMappingFor( attributeType );
        }
        catch ( LdapException ne )
        {
            errors.add( ne );
            LOG.info( ne.getMessage() );
        }
        
        // Update the cross references
        addCrossReferences( attributeType );
    }
    
    
    /**
     * Build the AttributeType references. This has to be done recursively, as
     * an AttributeType may inherit its parent's MatchingRules. The references
     * to update are :
     * - EQUALITY MR
     * - ORDERING MR
     * - SUBSTRING MR
     * - SUP AT
     * - SYNTAX
     */
    private void buildAttributeTypeReferences( List<Throwable> errors )
    {
        for ( AttributeType attributeType : attributeTypeRegistry )
        {
            if ( ( getUsing( attributeType ) == null ) || getUsing( attributeType ).isEmpty() )
            {
                buildReference( errors, attributeType );
            }
        }
    }


    /**
     * Build the Comparator references
     */
    private void buildComparatorReferences( List<Throwable> errors )
    {
        for ( LdapComparator<?> comparator : comparatorRegistry )
        {
            buildReference( errors, comparator );
        }
    }


    /**
     * Build the DitContentRule references
     */
    // Remove me when TODO is implemented
    @SuppressWarnings("PMD.UnusedFormalParameter")
    private void buildDitContentRuleReferences( List<Throwable> errors )
    {
        for ( DITContentRule ditContentRule : ditContentRuleRegistry )
        {
            // TODO
        }
    }


    /**
     * Build the DitStructureRule references
     */
    // Remove me when TODO is implemented
    @SuppressWarnings("PMD.UnusedFormalParameter")
    private void buildDitStructureRuleReferences( List<Throwable> errors )
    {
        for ( DITStructureRule ditStructureRule : ditStructureRuleRegistry )
        {
            // TODO
        }
    }


    /**
     * Delete the MR references (using and usedBy) : 
     * MR -> C
     * MR -> N
     * MR -> S
     */
    public void delCrossReferences( MatchingRule matchingRule )
    {
        if ( matchingRule.getLdapComparator() != null )
        {
            delReference( matchingRule, matchingRule.getLdapComparator() );
        }

        if ( matchingRule.getNormalizer() != null )
        {
            delReference( matchingRule, matchingRule.getNormalizer() );
        }

        if ( matchingRule.getSyntax() != null )
        {
            delReference( matchingRule, matchingRule.getSyntax() );
        }
    }


    /**
     * Build the SchemaObject references
     */
    public void buildReference( List<Throwable> errors, SchemaObject schemaObject )
    {
        try
        {
            schemaObject.addToRegistries( errors, this );
        }
        catch ( LdapException ne )
        {
            // Not allowed.
            String msg = I18n.err( I18n.ERR_04292, schemaObject.getName(), ne.getLocalizedMessage() );

            Throwable error = new LdapProtocolErrorException( msg );
            errors.add( error );
            LOG.info( msg );
        }
    }


    /**
     * Unlink the SchemaObject references
     */
    public void removeReference( List<Throwable> errors, SchemaObject schemaObject )
    {
        try
        {
            schemaObject.removeFromRegistries( errors, this );
        }
        catch ( LdapException ne )
        {
            // Not allowed.
            String msg = I18n.err( I18n.ERR_04293, schemaObject.getName(), ne.getLocalizedMessage() );

            Throwable error = new LdapSchemaViolationException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
            errors.add( error );
            LOG.info( msg );
        }
    }


    /**
     * Build the MatchingRule references
     */
    private void buildMatchingRuleReferences( List<Throwable> errors )
    {
        for ( MatchingRule matchingRule : matchingRuleRegistry )
        {
            buildReference( errors, matchingRule );
        }
    }


    /**
     * Build the MatchingRuleUse references
     */
    private void buildMatchingRuleUseReferences( List<Throwable> errors )
    {
        for ( MatchingRuleUse matchingRuleUse : matchingRuleUseRegistry )
        {
            buildReference( errors, matchingRuleUse );
        }
    }


    /**
     * Build the NameForm references
     */
    // Remove me when TODO is implemented
    @SuppressWarnings("PMD.UnusedFormalParameter")
    private void buildNameFormReferences( List<Throwable> errors )
    {
        for ( NameForm nameFormRule : nameFormRegistry )
        {
            // TODO
        }
    }


    /**
     * Build the Normalizer references
     */
    private void buildNormalizerReferences( List<Throwable> errors )
    {
        for ( Normalizer normalizer : normalizerRegistry )
        {
            buildReference( errors, normalizer );
        }
    }


    /**
     * Build the ObjectClasses references
     */
    private void buildObjectClassReferences( List<Throwable> errors )
    {
        // Remember the OC we have already processed
        Set<String> done = new HashSet<String>();

        // The ObjectClass
        for ( ObjectClass objectClass : objectClassRegistry )
        {
            if ( done.contains( objectClass.getOid() ) )
            {
                continue;
            }
            else
            {
                done.add( objectClass.getOid() );
            }

            buildReference( errors, objectClass );
        }
    }


    /**
     * Build the Syntax references
     */
    private void buildLdapSyntaxReferences( List<Throwable> errors )
    {
        for ( LdapSyntax syntax : ldapSyntaxRegistry )
        {
            buildReference( errors, syntax );
        }
    }


    /**
     * Build the SyntaxChecker references
     */
    private void buildSyntaxCheckerReferences( List<Throwable> errors )
    {
        for ( SyntaxChecker syntaxChecker : syntaxCheckerRegistry )
        {
            buildReference( errors, syntaxChecker );
        }
    }


    /**
     * Build the usedBy and using references from the stored elements.
     * 
     * @return A list of all the errors we met during the cross reference update
     */
    public List<Throwable> buildReferences()
    {
        List<Throwable> errors = new ArrayList<Throwable>();

        // The Comparator references
        buildComparatorReferences( errors );

        // The Normalizer references
        buildNormalizerReferences( errors );

        // The SyntaxChecker references
        buildSyntaxCheckerReferences( errors );

        // The Syntax references
        buildLdapSyntaxReferences( errors );

        // The MatchingRules references
        buildMatchingRuleReferences( errors );

        // The AttributeType references
        buildAttributeTypeReferences( errors );

        // The MatchingRuleUse references
        buildMatchingRuleUseReferences( errors );

        // The ObjectClasses references
        buildObjectClassReferences( errors );

        // The DitContentRules references
        buildDitContentRuleReferences( errors );

        // The NameForms references
        buildNameFormReferences( errors );

        // The DitStructureRules references
        buildDitStructureRuleReferences( errors );

        return errors;
    }


    /**
     * Attempts to resolve the SyntaxChecker associated with a Syntax.
     *
     * @param syntax the LdapSyntax to resolve the SyntaxChecker of
     * @param errors the list of errors to add exceptions to
     */
    private void resolve( LdapSyntax syntax, List<Throwable> errors )
    {
        // A LdapSyntax must point to a valid SyntaxChecker
        // or to the OctetString SyntaxChecker
        try
        {
            syntax.addToRegistries( errors, this );
        }
        catch ( LdapException e )
        {
            errors.add( e );
        }
    }


    /**
     * Attempts to resolve the Normalizer
     *
     * @param normalizer the Normalizer
     * @param errors the list of errors to add exceptions to
     */
    private void resolve( Normalizer normalizer, List<Throwable> errors )
    {
        // This is currently doing nothing.
        try
        {
            normalizer.addToRegistries( errors, this );
        }
        catch ( LdapException e )
        {
            errors.add( e );
        }
    }


    /**
     * Attempts to resolve the LdapComparator
     *
     * @param comparator the LdapComparator
     * @param errors the list of errors to add exceptions to
     */
    private void resolve( LdapComparator<?> comparator, List<Throwable> errors )
    {
        // This is currently doing nothing.
        try
        {
            comparator.addToRegistries( errors, this );
        }
        catch ( LdapException e )
        {
            errors.add( e );
        }
    }


    /**
     * Attempts to resolve the SyntaxChecker
     *
     * @param normalizer the SyntaxChecker
     * @param errors the list of errors to add exceptions to
     */
    private void resolve( SyntaxChecker syntaxChecker, List<Throwable> errors )
    {
        // This is currently doing nothing.
        try
        {
            syntaxChecker.addToRegistries( errors, this );
        }
        catch ( LdapException e )
        {
            errors.add( e );
        }
    }


    /**
     * Check if the Comparator, Normalizer and the syntax are 
     * existing for a matchingRule.
     */
    private void resolve( MatchingRule matchingRule, List<Throwable> errors )
    {
        // Process the Syntax. It can't be null
        String syntaxOid = matchingRule.getSyntaxOid();

        if ( syntaxOid != null )
        {
            // Check if the Syntax is present in the registries
            try
            {
                ldapSyntaxRegistry.lookup( syntaxOid );
            }
            catch ( LdapException ne )
            {
                // This MR's syntax has not been loaded into the Registries.
                errors.add( ne );
            }
        }
        else
        {
            // This is an error. 
            Throwable error = new LdapProtocolErrorException( I18n.err( I18n.ERR_04294, matchingRule.getOid() ) );
            errors.add( error );
        }

        // Process the Normalizer
        Normalizer normalizer = matchingRule.getNormalizer();

        if ( normalizer == null )
        {
            // Ok, no normalizer, this is an error
            Throwable error = new LdapSchemaViolationException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
                I18n.ERR_04295, matchingRule.getOid() ) );
            errors.add( error );
        }

        // Process the Comparator
        LdapComparator<?> comparator = matchingRule.getLdapComparator();

        if ( comparator == null )
        {
            // Ok, no comparator, this is an error
            Throwable error = new LdapSchemaViolationException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
                I18n.ERR_04296, matchingRule.getOid() ) );
            errors.add( error );
        }
    }


    /**
     * Check AttributeType referential integrity
     */
    private void resolveRecursive( AttributeType attributeType, Set<String> processed, List<Throwable> errors )
    {
        // Process the Superior, if any
        String superiorOid = attributeType.getSuperiorOid();

        AttributeType superior = null;

        if ( superiorOid != null )
        {
            // Check if the Superior is present in the registries
            try
            {
                superior = attributeTypeRegistry.lookup( superiorOid );
            }
            catch ( LdapException ne )
            {
                // This AT's superior has not been loaded into the Registries.
                if ( !processed.contains( superiorOid ) )
                {
                    errors.add( ne );
                }
            }

            // We now have to process the superior, if it hasn't been 
            // processed yet.
            if ( superior != null )
            {
                if ( !processed.contains( superiorOid ) )
                {
                    resolveRecursive( superior, processed, errors );
                    processed.add( attributeType.getOid() );
                }
                else
                {
                    // Not allowed : we have a cyle
                    Throwable error = new LdapSchemaViolationException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n
                        .err( I18n.ERR_04297, attributeType.getOid() ) );
                    errors.add( error );
                    return;
                }
            }
        }

        // Process the Syntax. If it's null, the attributeType must have 
        // a Superior.
        String syntaxOid = attributeType.getSyntaxOid();

        if ( syntaxOid != null )
        {
            // Check if the Syntax is present in the registries
            try
            {
                ldapSyntaxRegistry.lookup( syntaxOid );
            }
            catch ( LdapException ne )
            {
                // This AT's syntax has not been loaded into the Registries.
                errors.add( ne );
            }
        }
        else
        {
            // No Syntax : get it from the AttributeType's superior
            if ( superior == null )
            {
                // This is an error. if the AT does not have a Syntax,
                // then it must have a superior, which syntax is get from.
                Throwable error = new LdapSchemaViolationException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
                    I18n.ERR_04298, attributeType.getOid() ) );
                errors.add( error );
            }
        }

        // Process the EQUALITY MatchingRule. It may be null, but if it's not
        // it must have been processed before
        String equalityOid = attributeType.getEqualityOid();

        if ( equalityOid != null )
        {
            // Check if the MatchingRule is present in the registries
            try
            {
                matchingRuleRegistry.lookup( equalityOid );
            }
            catch ( LdapException ne )
            {
                // This AT's EQUALITY matchingRule has not been loaded into the Registries.
                errors.add( ne );
            }
        }

        // Process the ORDERING MatchingRule. It may be null, but if it's not
        // it must have been processed before
        String orderingOid = attributeType.getOrderingOid();

        if ( orderingOid != null )
        {
            // Check if the MatchingRule is present in the registries
            try
            {
                matchingRuleRegistry.lookup( orderingOid );
            }
            catch ( LdapException ne )
            {
                // This AT's ORDERING matchingRule has not been loaded into the Registries.
                errors.add( ne );
            }
        }

        // Process the SUBSTR MatchingRule. It may be null, but if it's not
        // it must have been processed before
        String substringOid = attributeType.getSubstringOid();

        if ( substringOid != null )
        {
            // Check if the MatchingRule is present in the registries
            try
            {
                matchingRuleRegistry.lookup( substringOid );
            }
            catch ( LdapException ne )
            {
                // This AT's SUBSTR matchingRule has not been loaded into the Registries.
                errors.add( ne );
            }
        }
    }


    /**
     * Check the inheritance, and the existence of MatchingRules and LdapSyntax
     * for an attribute 
     */
    private void resolve( AttributeType attributeType, List<Throwable> errors )
    {
        // This set is used to avoid having more than one error
        // for an AttributeType. It's mandatory when processing
        // a Superior, as it may be broken and referenced more than once. 
        Set<String> processed = new HashSet<String>();

        // Store the AttributeType itself in the processed, to avoid cycle
        processed.add( attributeType.getOid() );

        // Call the recursive method, as we may have superiors to deal with
        resolveRecursive( attributeType, processed, errors );
    }


    private List<AttributeType> getMustRecursive( List<AttributeType> musts, Set<ObjectClass> processed,
        ObjectClass objectClass )
    {
        if ( objectClass != null )
        {
            if ( processed.contains( objectClass ) )
            {
                // We have found a cycle. It has already been reported, 
                // don't add a new error, just exit.
                return null;
            }

            processed.add( objectClass );

            for ( AttributeType must : objectClass.getMustAttributeTypes() )
            {
                musts.add( must );
            }

            for ( ObjectClass superior : objectClass.getSuperiors() )
            {
                getMustRecursive( musts, processed, superior );
            }
        }

        return musts;
    }


    private void resolve( ObjectClass objectClass, List<Throwable> errors )
    {
        // This set is used to avoid having more than one error
        // for an ObjectClass. It's mandatory when processing
        // the Superiors, as they may be broken and referenced more than once. 
        Set<String> processed = new HashSet<String>();

        // Store the ObjectClass itself in the processed, to avoid cycle
        processed.add( objectClass.getOid() );

        // Call the recursive method, as we may have superiors to deal with
        resolveRecursive( objectClass, processed, errors );

        // Check that the MAY and MUST AT are consistent (no AT in MAY and in MUST
        // in one of its superior
        List<AttributeType> musts = getMustRecursive( new ArrayList<AttributeType>(), new HashSet<ObjectClass>(),
            objectClass );

        if ( musts != null )
        {
            for ( AttributeType may : objectClass.getMayAttributeTypes() )
            {
                if ( musts.contains( may ) )
                {
                    // This is not allowed.
                    Throwable error = new LdapProtocolErrorException( I18n.err( I18n.ERR_04299, objectClass.getOid() ) );
                    errors.add( error );
                    return;
                }
            }
        }
    }


    // This will suppress PMD.EmptyCatchBlock warnings in this method
    @SuppressWarnings("PMD.EmptyCatchBlock")
    private void resolveRecursive( ObjectClass objectClass, Set<String> processed, List<Throwable> errors )
    {
        // Process the Superiors, if any
        List<String> superiorOids = objectClass.getSuperiorOids();
        ObjectClass superior = null;

        for ( String superiorOid : superiorOids )
        {
            // Check if the Superior is present in the registries
            try
            {
                superior = objectClassRegistry.lookup( superiorOid );
            }
            catch ( LdapException ne )
            {
                // This OC's superior has not been loaded into the Registries.
                if ( !processed.contains( superiorOid ) )
                {
                    errors.add( ne );
                }
            }

            // We now have to process the superior, if it hasn't been 
            // processed yet.
            if ( superior != null )
            {
                if ( !processed.contains( superior.getOid() ) )
                {
                    resolveRecursive( superior, processed, errors );
                    processed.add( objectClass.getOid() );
                }
                else
                {
                    // Not allowed : we have a cyle
                    Throwable error = new LdapProtocolErrorException( I18n.err( I18n.ERR_04300, objectClass.getOid(),
                        superior ) );
                    errors.add( error );
                    return;
                }
            }
        }

        // Process the MAY attributeTypes.  
        for ( String mayOid : objectClass.getMayAttributeTypeOids() )
        {
            // Check if the MAY AttributeType is present in the registries
            try
            {
                attributeTypeRegistry.lookup( mayOid );
            }
            catch ( LdapException ne )
            {
                // This AT has not been loaded into the Registries.
                errors.add( ne );
            }
        }

        // Process the MUST attributeTypes.  
        for ( String mustOid : objectClass.getMustAttributeTypeOids() )
        {
            // Check if the MUST AttributeType is present in the registries
            try
            {
                attributeTypeRegistry.lookup( mustOid );
            }
            catch ( LdapException ne )
            {
                // This AT has not been loaded into the Registries.
                errors.add( ne );
            }
        }

        // All is done for this ObjectClass, let's apply the registries
        try
        {
            objectClass.addToRegistries( errors, this );
        }
        catch ( LdapException ne )
        {
            // Do nothing. We may have a broken OC, 
            // but at this point, it doesn't matter.
        }
    }


    /**
     * Applies the added SchemaObject to the given register
     */
    public List<Throwable> add( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
    {
        // Relax the registries
        boolean wasRelaxed = isRelaxed;
        setRelaxed();

        // Register the SchemaObject in the registries
        register( errors, schemaObject );

        // Associate the SchemaObject with its schema
        associateWithSchema( errors, schemaObject );

        // Build the SchemaObject references
        buildReference( errors, schemaObject );

        // Lock the SchemaObject
        schemaObject.lock();

        if ( errors.isEmpty() )
        {
            // Check the registries now
            List<Throwable> checkErrors = checkRefInteg();

            errors.addAll( checkErrors );
        }

        // Get back to Strict mode
        if ( !wasRelaxed )
        {
            setStrict();
        }

        // return the errors
        return errors;
    }


    /**
     * Remove the given SchemaObject from the registries
     */
    public List<Throwable> delete( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
    {
        // Relax the registries
        boolean wasRelaxed = isRelaxed;
        setRelaxed();

        // Remove the SchemaObject from the registries
        SchemaObject removed = unregister( errors, schemaObject );

        // Remove the SchemaObject from its schema
        dissociateFromSchema( errors, removed );

        // Unlink the SchemaObject references
        removeReference( errors, removed );

        if ( errors.isEmpty() )
        {
            // Check the registries now
            List<Throwable> checkErrors = checkRefInteg();

            errors.addAll( checkErrors );
        }

        // Restore the previous registries state
        if ( !wasRelaxed )
        {
            setStrict();
        }

        // return the errors
        return errors;
    }


    /**
     * Merely adds the schema to the set of loaded schemas.  Does not
     * actually do any work to add schema objects to registries.
     * 
     * {@inheritDoc}
     */
    public void schemaLoaded( Schema schema )
    {
        this.loadedSchemas.put( StringTools.toLowerCase( schema.getSchemaName() ), schema );
    }


    /**
     * Merely removes the schema from the set of loaded schemas.  Does not
     * actually do any work to remove schema objects from registries.
     * 
     * {@inheritDoc}
     */
    public void schemaUnloaded( Schema schema )
    {
        this.loadedSchemas.remove( StringTools.toLowerCase( schema.getSchemaName() ) );
    }


    /**
     * Gets an unmodifiable Map of schema names to loaded Schema objects. 
     * 
     * @return the map of loaded Schema objects
     */
    public Map<String, Schema> getLoadedSchemas()
    {
        return Collections.unmodifiableMap( loadedSchemas );
    }


    /**
     * @return Gets a reference to the Map associating a schemaName to
     * its contained SchemaObjects
     */
    public Map<String, Set<SchemaObjectWrapper>> getObjectBySchemaName()
    {
        return schemaObjects;
    }


    /**
     * Retrieve the schema name for a specific SchemaObject, or return "other" if none is found.
     */
    private String getSchemaName( SchemaObject schemaObject )
    {
        String schemaName = StringTools.toLowerCase( schemaObject.getSchemaName() );

        if ( loadedSchemas.containsKey( schemaName ) )
        {
            return schemaName;
        }
        else
        {
            return MetaSchemaConstants.SCHEMA_OTHER;
        }
    }


    /**
     * Tells if the given SchemaObject is present in one schema. The schema
     * may be disabled.
     *
     * @param schemaObject The schemaObject we are looking for
     * @return true if the schemaObject is present in a schema
     */
    public boolean contains( SchemaObject schemaObject )
    {
        String schemaName = schemaObject.getSchemaName();

        Set<SchemaObjectWrapper> setSchemaObjects = schemaObjects.get( schemaName );

        if ( ( setSchemaObjects == null ) || setSchemaObjects.isEmpty() )
        {
            return false;
        }

        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( schemaObject );

        return setSchemaObjects.contains( wrapper );
    }


    /**
     * Create a new schema association with its content
     *
     * @param schemaName The schema name
     */
    public Set<SchemaObjectWrapper> addSchema( String schemaName )
    {
        Set<SchemaObjectWrapper> content = new HashSet<SchemaObjectWrapper>();
        schemaObjects.put( schemaName, content );

        return content;
    }


    /**
     * Register the given SchemaObject into the associated Registry
     */
    private void register( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
    {
        LOG.debug( "Registering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );

        // Check that the SchemaObject is not already registered
        if ( schemaObject instanceof LoadableSchemaObject )
        {
            // TODO : Check for existing Loadable SchemaObject
        }
        else
        {
            if ( globalOidRegistry.contains( schemaObject.getOid() ) )
            {
                // TODO : throw an exception here
                String msg = I18n.err( I18n.ERR_04301, schemaObject.getObjectType(), schemaObject.getOid() );
                LOG.error( msg );
                Throwable error = new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
                errors.add( error );
                return;
            }
        }

        try
        {
            // First call the specific registry's register method
            switch ( schemaObject.getObjectType() )
            {
                case ATTRIBUTE_TYPE:
                    attributeTypeRegistry.register( ( AttributeType ) schemaObject );
                    break;

                case COMPARATOR:
                    comparatorRegistry.register( ( LdapComparator<?> ) schemaObject );
                    break;

                case DIT_CONTENT_RULE:
                    ditContentRuleRegistry.register( ( DITContentRule ) schemaObject );
                    break;

                case DIT_STRUCTURE_RULE:
                    ditStructureRuleRegistry.register( ( DITStructureRule ) schemaObject );
                    break;

                case LDAP_SYNTAX:
                    ldapSyntaxRegistry.register( ( LdapSyntax ) schemaObject );
                    break;

                case MATCHING_RULE:
                    matchingRuleRegistry.register( ( MatchingRule ) schemaObject );
                    break;

                case MATCHING_RULE_USE:
                    matchingRuleUseRegistry.register( ( MatchingRuleUse ) schemaObject );
                    break;

                case NAME_FORM:
                    nameFormRegistry.register( ( NameForm ) schemaObject );
                    break;

                case NORMALIZER:
                    normalizerRegistry.register( ( Normalizer ) schemaObject );
                    break;

                case OBJECT_CLASS:
                    objectClassRegistry.register( ( ObjectClass ) schemaObject );
                    break;

                case SYNTAX_CHECKER:
                    syntaxCheckerRegistry.register( ( SyntaxChecker ) schemaObject );
                    break;
            }
        }
        catch ( Exception e )
        {
            errors.add( e );
        }
    }


    /**
     * Store the given SchemaObject in the Map associating SchemaObjetcs to their
     * related Schema.
     *
     * @param schemaObject The schemaObject to register
     * @throws LdapException If there is a problem
     */
    public void associateWithSchema( List<Throwable> errors, SchemaObject schemaObject )
    {
        LOG.debug( "Registering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );

        // Check that the SchemaObject is not already registered
        if ( !( schemaObject instanceof LoadableSchemaObject ) && globalOidRegistry.contains( schemaObject.getOid() ) )
        {
            // TODO : throw an exception here
            String msg = I18n.err( I18n.ERR_04301, schemaObject.getObjectType(), schemaObject.getOid() );
            LOG.error( msg );
            Throwable error = new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
            errors.add( error );
            return;
        }

        // Get a normalized form of schema name
        String schemaName = getSchemaName( schemaObject );

        // And register the schemaObject within its schema
        Set<SchemaObjectWrapper> content = schemaObjects.get( schemaName );

        if ( content == null )
        {
            content = new HashSet<SchemaObjectWrapper>();
            schemaObjects.put( StringTools.toLowerCase( schemaName ), content );
        }

        SchemaObjectWrapper schemaObjectWrapper = new SchemaObjectWrapper( schemaObject );

        if ( content.contains( schemaObjectWrapper ) )
        {
            // Already present !
            // What should we do ?
            LOG.info( "Registering of {}:{} failed, is already present in the Registries",
                schemaObject.getObjectType(), schemaObject.getOid() );
        }
        else
        {
            // Create the association
            content.add( schemaObjectWrapper );

            // Update the global OidRegistry if the SchemaObject is not
            // an instance of LoadableSchemaObject
            if ( !( schemaObject instanceof LoadableSchemaObject ) )
            {
                try
                {
                    globalOidRegistry.register( schemaObject );
                }
                catch ( LdapException ne )
                {
                    errors.add( ne );
                    return;
                }
            }

            LOG.debug( "registered {} for OID {}", schemaObject.getName(), schemaObject.getOid() );
        }
    }


    /**
     * Store the given SchemaObject in the Map associating SchemaObjetcs to their
     * related Schema.
     *
     * @param schemaObject The schemaObject to register
     * @throws LdapException If there is a problem
     */

    public void dissociateFromSchema( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
    {
        LOG.debug( "Unregistering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );

        // Check that the SchemaObject is already registered
        if ( !( schemaObject instanceof LoadableSchemaObject ) && !globalOidRegistry.contains( schemaObject.getOid() ) )
        {
            // TODO : throw an exception here
            String msg = I18n.err( I18n.ERR_04302, schemaObject.getObjectType(), schemaObject.getOid() );
            LOG.error( msg );
            Throwable error = new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
            errors.add( error );
            return;
        }

        // Get a normalized form of schema name
        String schemaName = getSchemaName( schemaObject );
        String oid = schemaObject.getOid();

        // And unregister the schemaObject from its schema
        Set<SchemaObjectWrapper> content = schemaObjects.get( schemaName );

        SchemaObjectWrapper schemaObjectWrapper = new SchemaObjectWrapper( schemaObject );

        if ( !content.contains( schemaObjectWrapper ) )
        {
            // Not present !
            // What should we do ?
            LOG.info( "Unregistering of {}:{} failed, is not present in the Registries", schemaObject.getObjectType(),
                schemaObject.getOid() );
        }
        else
        {
            // Remove the association
            content.remove( schemaObjectWrapper );

            // Update the global OidRegistry if the SchemaObject is not
            // an instance of LoadableSchemaObject
            if ( !( schemaObject instanceof LoadableSchemaObject ) )
            {
                try
                {
                    globalOidRegistry.unregister( oid );
                }
                catch ( LdapException ne )
                {
                    errors.add( ne );
                    return;
                }
            }

            LOG.debug( "Unregistered {} for OID {}", schemaObject.getName(), schemaObject.getOid() );
        }
    }


    /**
     * Unregister a SchemaObject from the registries
     *
     * @param schemaObject The SchemaObject we want to deregister
     * @throws LdapException If the removal failed
     */
    // Remove me when TODO is implemented
    @SuppressWarnings("PMD.UnusedFormalParameter")
    private SchemaObject unregister( List<Throwable> errors, SchemaObject schemaObject ) throws LdapException
    {
        LOG.debug( "Unregistering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );

        // Check that the SchemaObject is present in the registries
        if ( schemaObject instanceof LoadableSchemaObject )
        {
            // TODO : check for an existing Loadable SchemaObject
        }
        else
        {
            if ( !globalOidRegistry.contains( schemaObject.getOid() ) )
            {
                // TODO : throw an exception here
                String msg = I18n.err( I18n.ERR_04302, schemaObject.getObjectType(), schemaObject.getOid() );
                LOG.error( msg );
                throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
            }
        }

        SchemaObject unregistered = null;

        // First call the specific registry's register method
        switch ( schemaObject.getObjectType() )
        {
            case ATTRIBUTE_TYPE:
                unregistered = attributeTypeRegistry.unregister( ( AttributeType ) schemaObject );
                break;

            case COMPARATOR:
                unregistered = comparatorRegistry.unregister( ( LdapComparator<?> ) schemaObject );
                break;

            case DIT_CONTENT_RULE:
                unregistered = ditContentRuleRegistry.unregister( ( DITContentRule ) schemaObject );
                break;

            case DIT_STRUCTURE_RULE:
                unregistered = ditStructureRuleRegistry.unregister( ( DITStructureRule ) schemaObject );
                break;

            case LDAP_SYNTAX:
                unregistered = ldapSyntaxRegistry.unregister( ( LdapSyntax ) schemaObject );
                break;

            case MATCHING_RULE:
                unregistered = matchingRuleRegistry.unregister( ( MatchingRule ) schemaObject );
                break;

            case MATCHING_RULE_USE:
                unregistered = matchingRuleUseRegistry.unregister( ( MatchingRuleUse ) schemaObject );
                break;

            case NAME_FORM:
                unregistered = nameFormRegistry.unregister( ( NameForm ) schemaObject );
                break;

            case NORMALIZER:
                unregistered = normalizerRegistry.unregister( ( Normalizer ) schemaObject );
                break;

            case OBJECT_CLASS:
                unregistered = objectClassRegistry.unregister( ( ObjectClass ) schemaObject );
                break;

            case SYNTAX_CHECKER:
                unregistered = syntaxCheckerRegistry.unregister( ( SyntaxChecker ) schemaObject );
                break;
        }

        return unregistered;
    }


    /**
     * Remove the given SchemaObject from the Map associating SchemaObjetcs to their
     * related Schema.
     *
     * @param schemaObject The schemaObject to remove
     * @throws LdapException If there is a problem
     */
    public void dissociateFromSchema( SchemaObject schemaObject ) throws LdapException
    {
        // And unregister the schemaObject within its schema
        Set<SchemaObjectWrapper> content = schemaObjects.get( StringTools.toLowerCase( schemaObject.getSchemaName() ) );

        if ( content != null )
        {
            SchemaObjectWrapper schemaObjectWrapper = new SchemaObjectWrapper( schemaObject );

            if ( content.contains( schemaObjectWrapper ) )
            {
                // remove the schemaObject
                content.remove( schemaObjectWrapper );

                // Update the global OidRegistry if the SchemaObject is not
                // an instance of LoadableSchemaObject
                if ( !( schemaObject instanceof LoadableSchemaObject ) )
                {
                    globalOidRegistry.unregister( schemaObject.getOid() );
                }

                LOG.debug( "Unregistered {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );
            }
            else
            {
                // Not present !!
                // What should we do ?
                LOG.debug( "Unregistering of {}:{} failed, not found in Registries", schemaObject.getObjectType(),
                    schemaObject.getOid() );
            }
        }
    }


    /**
     * Checks if a specific SchemaObject is referenced by any other SchemaObject.
     *
     * @param schemaObject The SchemaObject we are looking for
     * @return true if there is at least one SchemaObjetc referencing the given one
     */
    public boolean isReferenced( SchemaObject schemaObject )
    {
        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( schemaObject );

        Set<SchemaObjectWrapper> set = usedBy.get( wrapper );

        boolean referenced = ( set != null ) && ( set.size() != 0 );

        if ( LOG.isDebugEnabled() )
        {
            if ( referenced )
            {
                LOG.debug( "The {}:{} is referenced", schemaObject.getObjectType(), schemaObject.getOid() );
            }
            else
            {
                LOG.debug( "The {}:{} is not referenced", schemaObject.getObjectType(), schemaObject.getOid() );
            }
        }

        return referenced;
    }


    /**
     * Gets the Set of SchemaObjects referencing the given SchemaObject
     *
     * @param schemaObject The SchemaObject we are looking for
     * @return The Set of referencing SchemaObject, or null 
     */
    public Set<SchemaObjectWrapper> getUsedBy( SchemaObject schemaObject )
    {
        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( schemaObject );

        return usedBy.get( wrapper );
    }


    /**
     * Dump the UsedBy data structure as a String
     */
    public String dumpUsedBy()
    {
        StringBuilder sb = new StringBuilder();

        sb.append( "USED BY :\n" );

        for ( SchemaObjectWrapper wrapper : usedBy.keySet() )
        {
            sb.append( wrapper.get().getObjectType() ).append( '[' ).append( wrapper.get().getOid() ).append( "] : {" );

            boolean isFirst = true;

            for ( SchemaObjectWrapper uses : usedBy.get( wrapper ) )
            {
                if ( isFirst )
                {
                    isFirst = false;
                }
                else
                {
                    sb.append( ", " );
                }

                sb.append( uses.get().getObjectType() ).append( '[' ).append( wrapper.get().getOid() ).append( "]" );
            }

            sb.append( "}\n" );
        }

        return sb.toString();
    }


    /**
     * Dump the Using data structure as a String
     */
    public String dumpUsing()
    {
        StringBuilder sb = new StringBuilder();

        sb.append( "USING :\n" );

        for ( SchemaObjectWrapper wrapper : using.keySet() )
        {
            sb.append( wrapper.get().getObjectType() ).append( '[' ).append( wrapper.get().getOid() ).append( "] : {" );

            boolean isFirst = true;

            for ( SchemaObjectWrapper uses : using.get( wrapper ) )
            {
                if ( isFirst )
                {
                    isFirst = false;
                }
                else
                {
                    sb.append( ", " );
                }

                sb.append( uses.get().getObjectType() ).append( '[' ).append( wrapper.get().getOid() ).append( "]" );
            }

            sb.append( "}\n" );
        }

        return sb.toString();
    }


    /**
     * Gets the Set of SchemaObjects referenced by the given SchemaObject
     *
     * @param schemaObject The SchemaObject we are looking for
     * @return The Set of referenced SchemaObject, or null 
     */
    public Set<SchemaObjectWrapper> getUsing( SchemaObject schemaObject )
    {
        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( schemaObject );

        return using.get( wrapper );
    }


    /**
     * Add an association between a SchemaObject an the SchemaObject it refers
     *
     * @param reference The base SchemaObject
     * @param referee The SchemaObject pointing on the reference
     */
    private void addUsing( SchemaObject reference, SchemaObject referee )
    {
        if ( ( reference == null ) || ( referee == null ) )
        {
            return;
        }

        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( reference );

        Set<SchemaObjectWrapper> uses = getUsing( reference );

        if ( uses == null )
        {
            uses = new HashSet<SchemaObjectWrapper>();
        }

        uses.add( new SchemaObjectWrapper( referee ) );

        // Put back the set (this is a concurrentHashMap, it won't be replaced implicitly
        using.put( wrapper, uses );
    }


    /**
     * Add an association between a SchemaObject an the SchemaObject it refers
     *
     * @param base The base SchemaObject
     * @param referenced The referenced SchemaObject
     */
    public void addReference( SchemaObject base, SchemaObject referenced )
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( dump( "add", base, referenced ) );
        }

        addUsing( base, referenced );
        addUsedBy( referenced, base );

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( dumpUsedBy() );
            LOG.debug( dumpUsing() );
        }
    }


    /**
     * Add an association between a SchemaObject an the SchemaObject that refers it
     *
     * @param reference The base SchemaObject
     * @param referee The SchemaObject pointing on the reference
     */
    private void addUsedBy( SchemaObject referee, SchemaObject reference )
    {
        if ( ( reference == null ) || ( referee == null ) )
        {
            return;
        }

        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( referee );

        Set<SchemaObjectWrapper> uses = getUsedBy( referee );

        if ( uses == null )
        {
            uses = new HashSet<SchemaObjectWrapper>();
        }

        uses.add( new SchemaObjectWrapper( reference ) );

        // Put back the set (this is a concurrentHashMap, it won't be replaced implicitly
        usedBy.put( wrapper, uses );
    }


    /**
     * Del an association between a SchemaObject an the SchemaObject it refers
     *
     * @param reference The base SchemaObject
     * @param referee The SchemaObject pointing on the reference
     */
    private void delUsing( SchemaObject reference, SchemaObject referee )
    {
        if ( ( reference == null ) || ( referee == null ) )
        {
            return;
        }

        Set<SchemaObjectWrapper> uses = getUsing( reference );

        if ( uses == null )
        {
            return;
        }

        uses.remove( new SchemaObjectWrapper( referee ) );

        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( reference );

        if ( uses.size() == 0 )
        {
            using.remove( wrapper );
        }
        else
        {
            using.put( wrapper, uses );
        }
    }


    /**
     * Del an association between a SchemaObject an the SchemaObject that refers it
     *
     * @param reference The base SchemaObject
     * @param referee The SchemaObject pointing on the reference
     */
    private void delUsedBy( SchemaObject referee, SchemaObject reference )
    {
        if ( ( reference == null ) || ( referee == null ) )
        {
            return;
        }

        Set<SchemaObjectWrapper> uses = getUsedBy( referee );

        if ( uses == null )
        {
            return;
        }

        uses.remove( new SchemaObjectWrapper( reference ) );

        SchemaObjectWrapper wrapper = new SchemaObjectWrapper( referee );

        if ( uses.size() == 0 )
        {
            usedBy.remove( wrapper );
        }
        else
        {
            usedBy.put( wrapper, uses );
        }
    }


    /**
     * Delete an association between a SchemaObject an the SchemaObject it refers
     *
     * @param base The base SchemaObject
     * @param referenced The referenced SchemaObject
     */
    public void delReference( SchemaObject base, SchemaObject referenced )
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( dump( "del", base, referenced ) );
        }

        delUsing( base, referenced );
        delUsedBy( referenced, base );

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( dumpUsedBy() );
            LOG.debug( dumpUsing() );
        }
    }


    /**
     * Dump the reference operation as a String
     */
    private String dump( String op, SchemaObject reference, SchemaObject referee )
    {
        return op + " : " + reference.getObjectType() + "[" + reference.getOid() + "]/[" + referee.getObjectType()
            + "[" + referee.getOid() + "]";
    }


    private boolean checkReferences( SchemaObject reference, SchemaObject referee, String message )
    {
        SchemaObjectWrapper referenceWrapper = new SchemaObjectWrapper( reference );
        SchemaObjectWrapper refereeWrapper = new SchemaObjectWrapper( referee );

        // Check the references : Syntax -> SyntaxChecker
        if ( !using.containsKey( referenceWrapper ) )
        {
            LOG.debug( "The Syntax {}:{} does not reference any " + message, reference.getObjectType(), reference
                .getOid() );

            return false;
        }

        Set<SchemaObjectWrapper> usings = using.get( referenceWrapper );

        if ( !usings.contains( refereeWrapper ) )
        {
            LOG.debug( "The {}:{} does not reference any " + message, reference.getObjectType(), reference.getOid() );

            return false;
        }

        // Check the referees : SyntaxChecker -> Syntax
        if ( !usedBy.containsKey( refereeWrapper ) )
        {
            LOG.debug( "The {}:{} is not referenced by any " + message, referee.getObjectType(), referee.getOid() );

            return false;
        }

        Set<SchemaObjectWrapper> used = usedBy.get( refereeWrapper );

        if ( !used.contains( referenceWrapper ) )
        {
            LOG.debug( "The {}:{} is not referenced by any " + message, referee.getObjectType(), referee.getOid() );

            return false;
        }

        return true;
    }


    /**
     * Check the registries for invalid relations. This check stops at the first error.
     *
     * @return true if the Registries is consistent, false otherwise
     */
    public boolean check()
    {
        // Check the Syntaxes : check for a SyntaxChecker
        LOG.debug( "Checking Syntaxes" );

        for ( LdapSyntax syntax : ldapSyntaxRegistry )
        {
            // Check that each Syntax has a SyntaxChecker
            if ( syntax.getSyntaxChecker() == null )
            {
                LOG.debug( "The Syntax {} has no SyntaxChecker", syntax );

                return false;
            }

            if ( !syntaxCheckerRegistry.contains( syntax.getSyntaxChecker().getOid() ) )
            {
                LOG.debug( "Cannot find the SyntaxChecker {} for the Syntax {}", syntax.getSyntaxChecker().getOid(),
                    syntax );

                return false;
            }

            // Check the references : Syntax -> SyntaxChecker and SyntaxChecker -> Syntax 
            if ( !checkReferences( syntax, syntax.getSyntaxChecker(), "SyntaxChecker" ) )
            {
                return false;
            }
        }

        // Check the MatchingRules : check for a Normalizer, a Comparator and a Syntax
        LOG.debug( "Checking MatchingRules..." );

        for ( MatchingRule matchingRule : matchingRuleRegistry )
        {
            // Check that each MatchingRule has a Normalizer
            if ( matchingRule.getNormalizer() == null )
            {
                LOG.debug( "The MatchingRule {} has no Normalizer", matchingRule );

                return false;
            }

            // Check that each MatchingRule has a Normalizer
            if ( !normalizerRegistry.contains( matchingRule.getNormalizer().getOid() ) )
            {
                LOG.debug( "Cannot find the Normalizer {} for the MatchingRule {}", matchingRule.getNormalizer()
                    .getOid(), matchingRule );

                return false;
            }

            // Check that each MatchingRule has a Comparator
            if ( matchingRule.getLdapComparator() == null )
            {
                LOG.debug( "The MatchingRule {} has no Comparator", matchingRule );

                return false;
            }

            if ( !comparatorRegistry.contains( matchingRule.getLdapComparator().getOid() ) )
            {
                LOG.debug( "Cannot find the Comparator {} for the MatchingRule {}", matchingRule.getLdapComparator()
                    .getOid(), matchingRule );

                return false;
            }

            // Check that each MatchingRule has a Syntax
            if ( matchingRule.getSyntax() == null )
            {
                LOG.debug( "The MatchingRule {} has no Syntax", matchingRule );

                return false;
            }

            if ( !ldapSyntaxRegistry.contains( matchingRule.getSyntax().getOid() ) )
            {
                LOG.debug( "Cannot find the Syntax {} for the MatchingRule {}", matchingRule.getSyntax().getOid(),
                    matchingRule );

                return false;
            }

            // Check the references : MR -> S and S -> MR 
            if ( !checkReferences( matchingRule, matchingRule.getSyntax(), "Syntax" ) )
            {
                return false;
            }

            // Check the references : MR -> N 
            if ( !checkReferences( matchingRule, matchingRule.getNormalizer(), "Normalizer" ) )
            {
                return false;
            }

            // Check the references : MR -> C and C -> MR 
            if ( !checkReferences( matchingRule, matchingRule.getLdapComparator(), "Comparator" ) )
            {
                return false;
            }
        }

        // Check the ObjectClasses : check for MAY, MUST, SUPERIORS
        LOG.debug( "Checking ObjectClasses..." );

        for ( ObjectClass objectClass : objectClassRegistry )
        {
            // Check that each ObjectClass has all the MAY AttributeTypes
            if ( objectClass.getMayAttributeTypes() != null )
            {
                for ( AttributeType may : objectClass.getMayAttributeTypes() )
                {
                    if ( !attributeTypeRegistry.contains( may.getOid() ) )
                    {
                        LOG.debug( "Cannot find the AttributeType {} for the ObjectClass {} MAY", may, objectClass );

                        return false;
                    }

                    // Check the references : OC -> AT  and AT -> OC (MAY) 
                    if ( !checkReferences( objectClass, may, "AttributeType" ) )
                    {
                        return false;
                    }
                }
            }

            // Check that each ObjectClass has all the MUST AttributeTypes
            if ( objectClass.getMustAttributeTypes() != null )
            {
                for ( AttributeType must : objectClass.getMustAttributeTypes() )
                {
                    if ( !attributeTypeRegistry.contains( must.getOid() ) )
                    {
                        LOG.debug( "Cannot find the AttributeType {} for the ObjectClass {} MUST", must, objectClass );

                        return false;
                    }

                    // Check the references : OC -> AT  and AT -> OC (MUST) 
                    if ( !checkReferences( objectClass, must, "AttributeType" ) )
                    {
                        return false;
                    }
                }
            }

            // Check that each ObjectClass has all the SUPERIORS ObjectClasses
            if ( objectClass.getSuperiors() != null )
            {
                for ( ObjectClass superior : objectClass.getSuperiors() )
                {
                    if ( !objectClassRegistry.contains( objectClass.getOid() ) )
                    {
                        LOG.debug( "Cannot find the ObjectClass {} for the ObjectClass {} SUPERIORS", superior,
                            objectClass );

                        return false;
                    }

                    // Check the references : OC -> OC  and OC -> OC (SUPERIORS) 
                    if ( !checkReferences( objectClass, superior, "ObjectClass" ) )
                    {
                        return false;
                    }
                }
            }
        }

        // Check the AttributeTypes : check for MatchingRules, Syntaxes
        LOG.debug( "Checking AttributeTypes..." );

        for ( AttributeType attributeType : attributeTypeRegistry )
        {
            // Check that each AttributeType has a SYNTAX 
            if ( attributeType.getSyntax() == null )
            {
                LOG.debug( "The AttributeType {} has no Syntax", attributeType );

                return false;
            }

            if ( !ldapSyntaxRegistry.contains( attributeType.getSyntax().getOid() ) )
            {
                LOG.debug( "Cannot find the Syntax {} for the AttributeType {}", attributeType.getSyntax().getOid(),
                    attributeType );

                return false;
            }

            // Check the references for AT -> S and S -> AT
            if ( !checkReferences( attributeType, attributeType.getSyntax(), "AttributeType" ) )
            {
                return false;
            }

            // Check the EQUALITY MatchingRule
            if ( attributeType.getEquality() != null )
            {
                if ( !matchingRuleRegistry.contains( attributeType.getEquality().getOid() ) )
                {
                    LOG.debug( "Cannot find the MatchingRule {} for the AttributeType {}", attributeType.getEquality()
                        .getOid(), attributeType );

                    return false;
                }

                // Check the references for AT -> MR and MR -> AT
                if ( !checkReferences( attributeType, attributeType.getEquality(), "AttributeType" ) )
                {
                    return false;
                }
            }

            // Check the ORDERING MatchingRule
            if ( attributeType.getOrdering() != null )
            {
                if ( !matchingRuleRegistry.contains( attributeType.getOrdering().getOid() ) )
                {
                    LOG.debug( "Cannot find the MatchingRule {} for the AttributeType {}", attributeType.getOrdering()
                        .getOid(), attributeType );

                    return false;
                }

                // Check the references for AT -> MR and MR -> AT
                if ( !checkReferences( attributeType, attributeType.getOrdering(), "AttributeType" ) )
                {
                    return false;
                }
            }

            // Check the SUBSTR MatchingRule
            if ( attributeType.getSubstring() != null )
            {
                if ( !matchingRuleRegistry.contains( attributeType.getSubstring().getOid() ) )
                {
                    LOG.debug( "Cannot find the MatchingRule {} for the AttributeType {}", attributeType.getSubstring()
                        .getOid(), attributeType );

                    return false;
                }

                // Check the references for AT -> MR and MR -> AT
                if ( !checkReferences( attributeType, attributeType.getSubstring(), "AttributeType" ) )
                {
                    return false;
                }
            }

            // Check the SUP
            if ( attributeType.getSuperior() != null )
            {
                AttributeType superior = attributeType.getSuperior();

                if ( !attributeTypeRegistry.contains( superior.getOid() ) )
                {
                    LOG.debug( "Cannot find the AttributeType {} for the AttributeType {} SUPERIOR", superior,
                        attributeType );

                    return false;
                }

                // Check the references : AT -> AT  and AT -> AT (SUPERIOR) 
                if ( !checkReferences( attributeType, superior, "AttributeType" ) )
                {
                    return false;
                }
            }
        }

        return true;
    }


    /**
     * Clone the Registries. This is done in two steps :
     * - first clone the SchemaObjetc registries
     * - second restore the relation between them
     */
    // False positive
    @SuppressWarnings("PMD.EmptyCatchBlock")
    public Registries clone() throws CloneNotSupportedException
    {
        // First clone the structure
        Registries clone = ( Registries ) super.clone();

        // Now, clone the oidRegistry
        clone.globalOidRegistry = globalOidRegistry.copy();

        // We have to clone every SchemaObject registries now
        clone.attributeTypeRegistry = attributeTypeRegistry.copy();
        clone.comparatorRegistry = comparatorRegistry.copy();
        clone.ditContentRuleRegistry = ditContentRuleRegistry.copy();
        clone.ditStructureRuleRegistry = ditStructureRuleRegistry.copy();
        clone.ldapSyntaxRegistry = ldapSyntaxRegistry.copy();
        clone.matchingRuleRegistry = matchingRuleRegistry.copy();
        clone.matchingRuleUseRegistry = matchingRuleUseRegistry.copy();
        clone.nameFormRegistry = nameFormRegistry.copy();
        clone.normalizerRegistry = normalizerRegistry.copy();
        clone.objectClassRegistry = objectClassRegistry.copy();
        clone.syntaxCheckerRegistry = syntaxCheckerRegistry.copy();

        // Store all the SchemaObjects into the globalOid registry
        for ( AttributeType attributeType : clone.attributeTypeRegistry )
        {
            clone.globalOidRegistry.put( attributeType );
        }

        for ( DITContentRule ditContentRule : clone.ditContentRuleRegistry )
        {
            clone.globalOidRegistry.put( ditContentRule );
        }

        for ( DITStructureRule ditStructureRule : clone.ditStructureRuleRegistry )
        {
            clone.globalOidRegistry.put( ditStructureRule );
        }

        for ( MatchingRule matchingRule : clone.matchingRuleRegistry )
        {
            clone.globalOidRegistry.put( matchingRule );
        }

        for ( MatchingRuleUse matchingRuleUse : clone.matchingRuleUseRegistry )
        {
            clone.globalOidRegistry.put( matchingRuleUse );
        }

        for ( NameForm nameForm : clone.nameFormRegistry )
        {
            clone.globalOidRegistry.put( nameForm );
        }

        for ( ObjectClass objectClass : clone.objectClassRegistry )
        {
            clone.globalOidRegistry.put( objectClass );
        }

        for ( LdapSyntax syntax : clone.ldapSyntaxRegistry )
        {
            clone.globalOidRegistry.put( syntax );
        }

        // Clone the schema list
        clone.loadedSchemas = new HashMap<String, Schema>();

        for ( String schemaName : loadedSchemas.keySet() )
        {
            // We don't clone the schemas
            clone.loadedSchemas.put( schemaName, loadedSchemas.get( schemaName ) );
        }

        // Clone the Using and usedBy structures
        // They will be empty
        clone.using = new HashMap<SchemaObjectWrapper, Set<SchemaObjectWrapper>>();
        clone.usedBy = new HashMap<SchemaObjectWrapper, Set<SchemaObjectWrapper>>();

        // Last, rebuild the using and usedBy references
        clone.buildReferences();

        // Now, check the registries. We don't care about errors
        clone.checkRefInteg();

        clone.schemaObjects = new HashMap<String, Set<SchemaObjectWrapper>>();

        // Last, not least, clone the SchemaObjects Map, and reference all the copied
        // SchemaObjects
        for ( String schemaName : schemaObjects.keySet() )
        {
            Set<SchemaObjectWrapper> objects = new HashSet<SchemaObjectWrapper>();

            for ( SchemaObjectWrapper schemaObjectWrapper : schemaObjects.get( schemaName ) )
            {
                SchemaObject original = schemaObjectWrapper.get();

                try
                {
                    if ( !( original instanceof LoadableSchemaObject ) )
                    {
                        SchemaObject copy = clone.globalOidRegistry.getSchemaObject( original.getOid() );
                        SchemaObjectWrapper newWrapper = new SchemaObjectWrapper( copy );
                        objects.add( newWrapper );
                    }
                    else
                    {
                        SchemaObjectWrapper newWrapper = new SchemaObjectWrapper( original );
                        objects.add( newWrapper );
                    }
                }
                catch ( LdapException ne )
                {
                    // Nothing to do
                }
            }

            clone.schemaObjects.put( schemaName, objects );
        }

        return clone;
    }


    /**
     * Tells if the Registries is permissive or if it must be checked 
     * against inconsistencies.
     *
     * @return True if SchemaObjects can be added even if they break the consistency 
     */
    public boolean isRelaxed()
    {
        return isRelaxed;
    }


    /**
     * Tells if the Registries is strict.
     *
     * @return True if SchemaObjects cannot be added if they break the consistency 
     */
    public boolean isStrict()
    {
        return !isRelaxed;
    }


    /**
     * Change the Registries to a relaxed mode, where invalid SchemaObjects
     * can be registered.
     */
    public void setRelaxed()
    {
        isRelaxed = RELAXED;
    }


    /**
     * Change the Registries to a strict mode, where invalid SchemaObjects
     * cannot be registered.
     */
    public void setStrict()
    {
        isRelaxed = STRICT;
    }


    /**
     * Tells if the Registries accept disabled elements.
     *
     * @return True if disabled SchemaObjects can be added 
     */
    public boolean isDisabledAccepted()
    {
        return disabledAccepted;
    }


    /**
     * Check that we can remove a given SchemaObject without breaking some of its references.
     * We will return the list of refereing objects.
     *
     * @param schemaObject The SchemaObject to remove
     * @return The list of SchemaObjects referencing the SchemaObjetc we want to remove
     */
    public Set<SchemaObjectWrapper> getReferencing( SchemaObject schemaObject )
    {
        SchemaObjectWrapper schemaObjectWrapper = new SchemaObjectWrapper( schemaObject );

        return usedBy.get( schemaObjectWrapper );
    }


    /**
     * Change the Registries behavior regarding disabled SchemaObject element.
     *
     * @param disabledAccepted If <code>false</code>, then the Registries won't accept
     * disabled SchemaObject or enabled SchemaObject from disabled schema 
     */
    public void setDisabledAccepted( boolean disabledAccepted )
    {
        this.disabledAccepted = disabledAccepted;
    }


    /**
     * Clear the registries from all its elements
     *
     * @throws LdapException If something goes wrong
     */
    public void clear() throws LdapException
    {
        // The AttributeTypeRegistry
        if ( attributeTypeRegistry != null )
        {
            attributeTypeRegistry.clear();
        }

        // The ComparatorRegistry
        if ( comparatorRegistry != null )
        {
            comparatorRegistry.clear();
        }

        // The DitContentRuleRegistry
        if ( ditContentRuleRegistry != null )
        {
            ditContentRuleRegistry.clear();
        }

        // The DitStructureRuleRegistry
        if ( ditStructureRuleRegistry != null )
        {
            ditStructureRuleRegistry.clear();
        }

        // The MatchingRuleRegistry
        if ( matchingRuleRegistry != null )
        {
            matchingRuleRegistry.clear();
        }

        // The MatchingRuleUseRegistry
        if ( matchingRuleUseRegistry != null )
        {
            matchingRuleUseRegistry.clear();
        }

        // The NameFormRegistry
        if ( nameFormRegistry != null )
        {
            nameFormRegistry.clear();
        }

        // The NormalizerRegistry
        if ( normalizerRegistry != null )
        {
            normalizerRegistry.clear();
        }

        // The ObjectClassRegistry
        if ( objectClassRegistry != null )
        {
            objectClassRegistry.clear();
        }

        // The SyntaxRegistry
        if ( ldapSyntaxRegistry != null )
        {
            ldapSyntaxRegistry.clear();
        }

        // The SyntaxCheckerRegistry
        if ( syntaxCheckerRegistry != null )
        {
            syntaxCheckerRegistry.clear();
        }

        // Clear the schemaObjects map
        for ( String schemaName : schemaObjects.keySet() )
        {
            Set<SchemaObjectWrapper> wrapperSet = schemaObjects.get( schemaName );

            wrapperSet.clear();
        }

        schemaObjects.clear();

        // Clear the usedBy map
        for ( SchemaObjectWrapper wrapper : usedBy.keySet() )
        {
            Set<SchemaObjectWrapper> wrapperSet = usedBy.get( wrapper );

            wrapperSet.clear();
        }

        usedBy.clear();

        // Clear the using map
        for ( SchemaObjectWrapper wrapper : using.keySet() )
        {
            Set<SchemaObjectWrapper> wrapperSet = using.get( wrapper );

            wrapperSet.clear();
        }

        using.clear();

        // Clear the global OID registry
        globalOidRegistry.clear();

        // Clear the loadedSchema Map
        loadedSchemas.clear();
    }


    /**
     * @see Object#toString()
     */
    public String toString()
    {
        StringBuilder sb = new StringBuilder();

        sb.append( "Registries [" );

        if ( isRelaxed )
        {
            sb.append( "RELAXED," );
        }
        else
        {
            sb.append( "STRICT," );
        }

        if ( disabledAccepted )
        {
            sb.append( " Disabled accepted] :\n" );
        }
        else
        {
            sb.append( " Disabled forbidden] :\n" );
        }

        sb.append( "loaded schemas [" );
        boolean isFirst = true;

        for ( String schema : loadedSchemas.keySet() )
        {
            if ( isFirst )
            {
                isFirst = false;
            }
            else
            {
                sb.append( ", " );
            }

            sb.append( schema );
        }

        sb.append( "]\n" );

        sb.append( "AttributeTypes : " ).append( attributeTypeRegistry.size() ).append( "\n" );
        sb.append( "Comparators : " ).append( comparatorRegistry.size() ).append( "\n" );
        sb.append( "DitContentRules : " ).append( ditContentRuleRegistry.size() ).append( "\n" );
        sb.append( "DitStructureRules : " ).append( ditStructureRuleRegistry.size() ).append( "\n" );
        sb.append( "MatchingRules : " ).append( matchingRuleRegistry.size() ).append( "\n" );
        sb.append( "MatchingRuleUses : " ).append( matchingRuleUseRegistry.size() ).append( "\n" );
        sb.append( "NameForms : " ).append( nameFormRegistry.size() ).append( "\n" );
        sb.append( "Normalizers : " ).append( normalizerRegistry.size() ).append( "\n" );
        sb.append( "ObjectClasses : " ).append( objectClassRegistry.size() ).append( "\n" );
        sb.append( "Syntaxes : " ).append( ldapSyntaxRegistry.size() ).append( "\n" );
        sb.append( "SyntaxCheckers : " ).append( syntaxCheckerRegistry.size() ).append( "\n" );

        sb.append( "GlobalOidRegistry : " ).append( globalOidRegistry.size() ).append( '\n' );

        return sb.toString();
    }
}
