/*
 *  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.model.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.model.constants.MetaSchemaConstants;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.apache.directory.shared.ldap.model.exception.LdapProtocolErrorException;
import org.apache.directory.shared.ldap.model.exception.LdapSchemaException;
import org.apache.directory.shared.ldap.model.exception.LdapSchemaExceptionCodes;
import org.apache.directory.shared.ldap.model.exception.LdapSchemaViolationException;
import org.apache.directory.shared.ldap.model.exception.LdapUnwillingToPerformException;
import org.apache.directory.shared.ldap.model.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.model.schema.MutableAttributeTypeImpl;
import org.apache.directory.shared.ldap.model.schema.DITContentRule;
import org.apache.directory.shared.ldap.model.schema.DITStructureRule;
import org.apache.directory.shared.ldap.model.schema.AbstractLdapComparator;
import org.apache.directory.shared.ldap.model.schema.LdapSyntax;
import org.apache.directory.shared.ldap.model.schema.MutableLdapComparator;
import org.apache.directory.shared.ldap.model.schema.MutableLdapSyntax;
import org.apache.directory.shared.ldap.model.schema.MutableLdapSyntaxImpl;
import org.apache.directory.shared.ldap.model.schema.MutableLoadableSchemaObject;
import org.apache.directory.shared.ldap.model.schema.MutableMatchingRule;
import org.apache.directory.shared.ldap.model.schema.MutableMatchingRuleImpl;
import org.apache.directory.shared.ldap.model.schema.MatchingRuleUse;
import org.apache.directory.shared.ldap.model.schema.MutableNormalizer;
import org.apache.directory.shared.ldap.model.schema.MutableSyntaxChecker;
import org.apache.directory.shared.ldap.model.schema.NameForm;
import org.apache.directory.shared.ldap.model.schema.AbstractNormalizer;
import org.apache.directory.shared.ldap.model.schema.Normalizer;
import org.apache.directory.shared.ldap.model.schema.ObjectClass;
import org.apache.directory.shared.ldap.model.schema.SchemaManager;
import org.apache.directory.shared.ldap.model.schema.MutableSchemaObject;
import org.apache.directory.shared.ldap.model.schema.SchemaObject;
import org.apache.directory.shared.ldap.model.schema.SchemaObjectWrapper;
import org.apache.directory.shared.ldap.model.schema.SyntaxChecker;
import org.apache.directory.shared.util.Strings;
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<MutableLdapComparator<?>> comparatorRegistry;

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

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

    /** The MatchingRule registry */
    protected MatchingRuleRegistry<MutableMatchingRule> matchingRuleRegistry;

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

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

    /** The Normalizer registry */
    protected NormalizerRegistry<MutableNormalizer> normalizerRegistry;

    /** The global OID registry */
    protected OidRegistry<MutableSchemaObject> globalOidRegistry;

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

    /** The LdapSyntax registry */
    protected DefaultLdapSyntaxRegistry 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;


    /**
     * Creates a new instance of Registries.
     *
     * @param schemaManager the schema manager
     */
    public Registries( SchemaManager schemaManager )
    {
        globalOidRegistry = new OidRegistry<MutableSchemaObject>();
        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;
    }


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


    /**
     * @return The Comparator registry
     */
    public ComparatorRegistry<MutableLdapComparator<?>> 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<MutableMatchingRule> 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<MutableNormalizer> getNormalizerRegistry()
    {
        return normalizerRegistry;
    }


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


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


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


    /**
     * @return The LdapSyntax registry
     */
    public LdapSyntaxRegistry<MutableLdapSyntax> 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
     */
    public String getOid( String name )
    {
        // we have many possible Registries to look at.
        // AttributeType
        try
        {
            MutableAttributeTypeImpl 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
        {
            MutableMatchingRule 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( Strings.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( Strings.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 ( MutableNormalizer normalizer : normalizerRegistry )
        {
            resolve( normalizer, errors );
        }

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

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

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

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

        // Step 4 :
        // Check the AttributeTypes
        for ( MutableAttributeTypeImpl 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( MutableAttributeTypeImpl 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 ( MutableAttributeTypeImpl attributeType : attributeTypeRegistry )
        {
            if ( ( getUsing( attributeType ) == null ) || getUsing( attributeType ).isEmpty() )
            {
                buildReference( errors, attributeType );
            }
        }
    }


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


    /**
     * Build the DitContentRule references
     */
    private void buildDitContentRuleReferences( List<Throwable> errors )
    {
        for ( @SuppressWarnings("unused") DITContentRule ditContentRule : ditContentRuleRegistry )
        {
            // TODO
        }
    }


    /**
     * Build the DitStructureRule references
     */
    private void buildDitStructureRuleReferences( List<Throwable> errors )
    {
        for ( @SuppressWarnings("unused") DITStructureRule ditStructureRule : ditStructureRuleRegistry )
        {
            // TODO
        }
    }


    /**
     * Delete the MR references (using and usedBy) : 
     * MR -> C
     * MR -> N
     * MR -> S
     */
    public void delCrossReferences( MutableMatchingRuleImpl 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, MutableSchemaObject 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, MutableSchemaObject 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 ( MutableMatchingRule 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
     */
    private void buildNameFormReferences( List<Throwable> errors )
    {
        for ( @SuppressWarnings("unused") NameForm nameFormRule : nameFormRegistry )
        {
            // TODO
        }
    }


    /**
     * Build the Normalizer references
     */
    private void buildNormalizerReferences( List<Throwable> errors )
    {
        for ( MutableNormalizer 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 ( MutableLdapSyntax syntax : ldapSyntaxRegistry )
        {
            buildReference( errors, syntax );
        }
    }


    /**
     * Build the SyntaxChecker references
     */
    private void buildSyntaxCheckerReferences( List<Throwable> errors )
    {
        for ( SyntaxChecker syntaxChecker : syntaxCheckerRegistry )
        {
            buildReference( errors, ( MutableSyntaxChecker ) 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( MutableLdapSyntax syntax, List<Throwable> errors )
    {
        // A LdapSyntax must point to a valid SyntaxChecker or to the default
        try
        {
            RegistryUtils.addToRegistries( errors, syntax, 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( MutableNormalizer 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( MutableLdapComparator<?> 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( MutableSyntaxChecker 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( MutableMatchingRule 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.
                LdapSchemaException ldapSchemaException = new LdapSchemaException(
                    LdapSchemaExceptionCodes.OID_ALREADY_REGISTERED, I18n.err( I18n.ERR_04294, matchingRule.getOid() ) );
                ldapSchemaException.setSourceObject( matchingRule );
                errors.add( ldapSchemaException );
            }
        }
        else
        {
            // This is an error. 
            LdapSchemaException ldapSchemaException = new LdapSchemaException(
                LdapSchemaExceptionCodes.OID_ALREADY_REGISTERED, I18n.err( I18n.ERR_04294, matchingRule.getOid() ) );
            ldapSchemaException.setSourceObject( matchingRule );
            errors.add( ldapSchemaException );
        }

        // 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
        MutableLdapComparator<?> 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( MutableAttributeTypeImpl attributeType, Set<String> processed, List<Throwable> errors )
    {
        // Process the Superior, if any
        String superiorOid = attributeType.getSuperiorOid();

        MutableAttributeTypeImpl 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( MutableAttributeTypeImpl 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<MutableAttributeTypeImpl> getMustRecursive( List<MutableAttributeTypeImpl> 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 ( MutableAttributeTypeImpl 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<MutableAttributeTypeImpl> musts = getMustRecursive( new ArrayList<MutableAttributeTypeImpl>(), new HashSet<ObjectClass>(),
            objectClass );

        if ( musts != null )
        {
            for ( MutableAttributeTypeImpl may : objectClass.getMayAttributeTypes() )
            {
                if ( musts.contains( may ) )
                {
                    // This is not allowed.
                    LdapSchemaException ldapSchemaException = new LdapSchemaException(
                        LdapSchemaExceptionCodes.OC_DUPLICATE_AT_IN_MAY_AND_MUST );
                    ldapSchemaException.setSourceObject( objectClass );
                    ldapSchemaException.setOtherObject( may );
                    errors.add( ldapSchemaException );
                    return;
                }
            }
        }
    }


    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 ) )
                {
                    LdapSchemaException ldapSchemaException = new LdapSchemaException(
                        LdapSchemaExceptionCodes.OC_NONEXISTENT_SUPERIOR );
                    ldapSchemaException.setSourceObject( objectClass );
                    ldapSchemaException.setRelatedId( superiorOid );
                    errors.add( ldapSchemaException );
                }
            }

            // 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
                    LdapSchemaException ldapSchemaException = new LdapSchemaException(
                        LdapSchemaExceptionCodes.OC_CYCLE_CLASS_HIERARCHY );
                    ldapSchemaException.setSourceObject( objectClass );
                    ldapSchemaException.setOtherObject( superior );
                    errors.add( ldapSchemaException );
                    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, MutableSchemaObject 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 );

        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
        MutableSchemaObject 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( Strings.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( Strings.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 = Strings.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( MutableSchemaObject 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 MutableLoadableSchemaObject )
        {
            // 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( ( MutableAttributeTypeImpl ) schemaObject );
                    break;

                case COMPARATOR:
                    comparatorRegistry.register( ( AbstractLdapComparator<?> ) 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( ( MutableLdapSyntaxImpl ) schemaObject );
                    break;

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

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

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

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

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

                case SYNTAX_CHECKER:
                    syntaxCheckerRegistry.register( ( MutableSyntaxChecker ) 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 MutableLoadableSchemaObject ) && 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( Strings.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 MutableLoadableSchemaObject ) )
            {
                try
                {
                    globalOidRegistry.register( ( MutableSchemaObject ) 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, MutableSchemaObject schemaObject ) throws LdapException
    {
        LOG.debug( "Unregistering {}:{}", schemaObject.getObjectType(), schemaObject.getOid() );

        // Check that the SchemaObject is already registered
        if ( !( schemaObject instanceof MutableLoadableSchemaObject ) && !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 MutableLoadableSchemaObject ) )
            {
                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
     */
    private MutableSchemaObject 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 MutableLoadableSchemaObject )
        {
            // 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 );
            }
        }

        MutableSchemaObject unregistered = null;

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

            case COMPARATOR:
                unregistered = comparatorRegistry.unregister( ( AbstractLdapComparator<?> ) 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( ( MutableLdapSyntax ) schemaObject );
                break;

            case MATCHING_RULE:
                unregistered = matchingRuleRegistry.unregister( ( MutableMatchingRuleImpl ) 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( ( MutableNormalizer ) schemaObject );
                break;

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

            case SYNTAX_CHECKER:
                unregistered = syntaxCheckerRegistry.unregister( ( MutableSyntaxChecker ) 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( MutableSchemaObject schemaObject ) throws LdapException
    {
        // And unregister the schemaObject within its schema
        Set<SchemaObjectWrapper> content = schemaObjects.get( Strings.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 MutableLoadableSchemaObject ) )
                {
                    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( MutableSchemaObject 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( MutableSchemaObject 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( MutableSchemaObject 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( MutableSchemaObject reference, MutableSchemaObject 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( MutableSchemaObject base, MutableSchemaObject 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( MutableSchemaObject referee, MutableSchemaObject 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( MutableSchemaObject reference, MutableSchemaObject 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( MutableSchemaObject referee, MutableSchemaObject 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( MutableSchemaObject base, MutableSchemaObject 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( MutableSchemaObject reference, MutableSchemaObject 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 ( MutableLdapSyntax 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 ( MutableMatchingRule 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 ( MutableAttributeTypeImpl 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 ( MutableAttributeTypeImpl 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 ( MutableAttributeTypeImpl 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 )
            {
                MutableAttributeTypeImpl 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
     */
    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 ( MutableAttributeTypeImpl 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 ( MutableMatchingRule 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 ( MutableLdapSyntax 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 MutableLoadableSchemaObject ) )
                    {
                        MutableSchemaObject 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();
    }
}
