/*
 *  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.AttributeType;
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
        {
            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
        {
            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 ( 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 ( 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( 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.
                    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( ( AttributeType ) 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( ( AttributeType ) 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 ( 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
     */
    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 ( 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();
    }
}
