/*
 *  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.schemaloader;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import com.mycila.junit.concurrent.Concurrency;
import com.mycila.junit.concurrent.ConcurrentJunitRunner;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.apache.directory.shared.ldap.model.exception.LdapSchemaException;
import org.apache.directory.shared.ldap.model.schema.MutableAttributeTypeImpl;
import org.apache.directory.shared.ldap.model.schema.AbstractLdapComparator;
import org.apache.directory.shared.ldap.model.schema.LdapComparator;
import org.apache.directory.shared.ldap.model.schema.LdapSyntax;
import org.apache.directory.shared.ldap.model.schema.MatchingRule;
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.MutableMatchingRule;
import org.apache.directory.shared.ldap.model.schema.MutableMatchingRuleImpl;
import org.apache.directory.shared.ldap.model.schema.MutableNormalizer;
import org.apache.directory.shared.ldap.model.schema.AbstractNormalizer;
import org.apache.directory.shared.ldap.model.schema.ObjectClass;
import org.apache.directory.shared.ldap.model.schema.ObjectClassTypeEnum;
import org.apache.directory.shared.ldap.model.schema.SchemaManager;
import org.apache.directory.shared.ldap.model.schema.AbstractSyntaxChecker;
import org.apache.directory.shared.ldap.model.schema.SyntaxChecker;
import org.apache.directory.shared.ldap.model.schema.UsageEnum;
import org.apache.directory.shared.ldap.model.schema.comparators.BooleanComparator;
import org.apache.directory.shared.ldap.model.schema.comparators.ComparableComparator;
import org.apache.directory.shared.ldap.model.schema.comparators.CsnComparator;
import org.apache.directory.shared.ldap.model.schema.normalizers.NoOpNormalizer;
import org.apache.directory.shared.ldap.model.schema.syntaxCheckers.OctetStringSyntaxChecker;
import org.apache.directory.shared.ldap.model.schema.syntaxCheckers.RegexSyntaxChecker;
import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * A test class for SchemaManager, testig the addition of a SchemaObject.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@RunWith(ConcurrentJunitRunner.class)
@Concurrency()
public class SchemaManagerAddTest
{
    // A directory in which the ldif files will be stored
    private static String workingDirectory;

    // The schema repository
    private static File schemaRepository;


    @BeforeClass
    public static void setup() throws Exception
    {
        workingDirectory = System.getProperty( "workingDirectory" );

        if ( workingDirectory == null )
        {
            String path = SchemaManagerAddTest.class.getResource( "" ).getPath();
            int targetPos = path.indexOf( "target" );
            workingDirectory = path.substring( 0, targetPos + 6 );
        }

        // Make sure every test class has its own schema directory
        workingDirectory = new File( workingDirectory, "SchemaManagerAddTest" ).getAbsolutePath();

        schemaRepository = new File( workingDirectory, "schema" );

        // Cleanup the target directory
        FileUtils.deleteDirectory( schemaRepository );

        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
        extractor.extractOrCopy();
    }


    @AfterClass
    public static void cleanup() throws IOException
    {
        // Cleanup the target directory
        FileUtils.deleteDirectory( schemaRepository.getParentFile() );
    }


    private SchemaManager loadSystem() throws Exception
    {
        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
        SchemaManager schemaManager = new DefaultSchemaManager( loader );

        String schemaName = "system";

        schemaManager.loadWithDeps( schemaName );

        return schemaManager;
    }


    /**
     * Check if an AT is present in the AT registry
     */
    private boolean isATPresent( SchemaManager schemaManager, String oid )
    {
        try
        {
            MutableAttributeTypeImpl attributeType = schemaManager.lookupAttributeTypeRegistry( oid );

            return attributeType != null;
        }
        catch ( LdapException ne )
        {
            return false;
        }
    }


    /**
     * Check if a MR is present in the MR registry
     */
    private boolean isMRPresent( SchemaManager schemaManager, String oid )
    {
        try
        {
            MatchingRule matchingRule = schemaManager.lookupMatchingRuleRegistry( oid );

            return matchingRule != null;
        }
        catch ( LdapException ne )
        {
            return false;
        }
    }


    /**
     * Check if an OC is present in the OC registry
     */
    private boolean isOCPresent( SchemaManager schemaManager, String oid )
    {
        try
        {
            ObjectClass objectClass = schemaManager.lookupObjectClassRegistry( oid );

            return objectClass != null;
        }
        catch ( LdapException ne )
        {
            return false;
        }
    }


    /**
     * Check if a S is present in the S registry
     */
    private boolean isSyntaxPresent( SchemaManager schemaManager, String oid )
    {
        try
        {
            LdapSyntax syntax = schemaManager.lookupLdapSyntaxRegistry( oid );

            return syntax != null;
        }
        catch ( LdapException ne )
        {
            return false;
        }
    }


    //=========================================================================
    // For each test, we will check many different things.
    // If the test is successful, we want to know if the SchemaObject
    // Registry has grown : its size must be one bigger. If the SchemaObject
    // is not loadable, then the GlobalOidRegistry must also have grown.
    //=========================================================================
    // AttributeType addition tests
    //-------------------------------------------------------------------------
    // First, not defined superior
    //-------------------------------------------------------------------------
    /**
     * Try to inject an AttributeType without any superior nor Syntax : it's invalid
     */
    @Test
    public void testAddAttributeTypeNoSupNoSyntaxNoSuperior() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType which is Collective, and userApplication AT
     */
    @Test
    public void testAddAttributeTypeNoSupCollectiveUser() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );
        attributeType.setCollective( true );

        // It should not fail
        assertTrue( schemaManager.add( attributeType ) );

        assertTrue( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType which is a subtype of a Collective AT
     */
    @Test
    public void testAddAttributeTypeSupCollectiveUser() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        // Create the collective attribute first
        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );
        attributeType.setCollective( true );

        // It should not fail
        assertTrue( schemaManager.add( attributeType ) );

        assertTrue( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );

        // Now try to create an AT which is a subtype of teh create collective attribute
        MutableAttributeTypeImpl subType = new MutableAttributeTypeImpl( "1.1.1" );
        subType.setEqualityOid( "2.5.13.1" );
        subType.setOrderingOid( null );
        subType.setSubstringOid( null );
        subType.setSuperiorOid( "1.1.0" );
        subType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        subType.setUsage( UsageEnum.USER_APPLICATIONS );
        subType.setCollective( false );

        // It should fail
        assertFalse( schemaManager.add( subType ) );

        assertFalse( isATPresent( schemaManager, "1.1.1" ) );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType which is Collective, but an operational AT
     */
    @Test
    public void testAddAttributeTypeNoSupCollectiveOperational() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.DIRECTORY_OPERATION );
        attributeType.setCollective( true );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a single valued AttributeType which is Collective
     */
    @Test
    public void testAddAttributeTypeCollectiveOperationalSigleValue() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );
        attributeType.setCollective( true );
        attributeType.setSingleValued( true );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType which is a NO-USER-MODIFICATION and userApplication
     */
    @Test
    public void testAddAttributeTypeNoSupNoUserModificationUserAplication() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );
        attributeType.setUserModifiable( false );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType which is a NO-USER-MODIFICATION and is operational
     */
    @Test
    public void testAddAttributeTypeNoSupNoUserModificationOpAttr() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.DISTRIBUTED_OPERATION );
        attributeType.setUserModifiable( false );

        // It should not fail
        assertTrue( schemaManager.add( attributeType ) );

        assertTrue( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with an invalid EQUALITY MR
     */
    @Test
    public void testAddAttributeTypeNoSupInvalidEqualityMR() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "0.0" );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType without EQUALITY MR
     */
    @Test
    public void testAddAttributeTypeNoEqualityMR() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.8 " );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );

        // It should be OK
        assertTrue( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );

        assertTrue( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with an invalid ORDERING MR
     */
    @Test
    public void testAddAttributeTypeNoSupInvalidOrderingMR() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( null );
        attributeType.setOrderingOid( "0.0" );
        attributeType.setSubstringOid( null );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with an invalid SUBSTR MR
     */
    @Test
    public void testAddAttributeTypeNoSupInvalidSubstringMR() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( null );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( "0.0" );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with valid MRs
     */
    @Test
    public void testAddAttributeTypeNoSupValidMR() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( "2.5.13.1" );
        attributeType.setSubstringOid( "2.5.13.1" );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setUsage( UsageEnum.USER_APPLICATIONS );

        // It should not fail
        assertTrue( schemaManager.add( attributeType ) );

        assertTrue( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType which already exist
     */
    @Test
    public void testAddAttributeTypeAlreadyExist() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "2.5.18.4" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( "2.5.13.1" );
        attributeType.setSubstringOid( "2.5.13.1" );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        // The AT must be there
        assertTrue( isATPresent( schemaManager, "2.5.18.4" ) );

        // Check that it hasen't changed
        MutableAttributeTypeImpl original = schemaManager.lookupAttributeTypeRegistry( "2.5.18.4" );
        assertEquals( "distinguishedNameMatch", original.getEqualityOid() );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with an already attributed name
     */
    @Test
    public void testAddAttributeTypeNameAlreadyExist() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( "2.5.13.1" );
        attributeType.setSubstringOid( "2.5.13.1" );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setNames( "Test", "cn" );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        // The AT must not be there
        assertFalse( isATPresent( schemaManager, "1.1.1.0" ) );

        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with an ObjectClass name
     */
    @Test
    public void testAddAttributeTypeNameOfAnObjectClass() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.1.0" );
        attributeType.setEqualityOid( "2.5.13.1" );
        attributeType.setOrderingOid( "2.5.13.1" );
        attributeType.setSubstringOid( "2.5.13.1" );
        attributeType.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        attributeType.setNames( "Test", "referral" );

        // It should be ok
        assertTrue( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );

        // The AT must be present
        assertTrue( isATPresent( schemaManager, "1.1.1.0" ) );

        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );

        MutableAttributeTypeImpl added = schemaManager.lookupAttributeTypeRegistry( "referral" );
        assertNotNull( added );
        assertEquals( "1.1.1.0", added.getOid() );
        assertTrue( added.getNames().contains( "referral" ) );
    }


    //-------------------------------------------------------------------------
    // Then, with a superior
    //-------------------------------------------------------------------------
    /**
     * Try to inject an AttributeType with a superior and no Syntax : it should
     * take its superior' syntax and MR
     */
    @Test
    public void testAddAttributeTypeSupNoSyntaxNoSuperior() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( null );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSuperiorOid( "2.5.18.4" );
        attributeType.setUsage( UsageEnum.DIRECTORY_OPERATION );

        // It should not fail
        assertTrue( schemaManager.add( attributeType ) );

        MutableAttributeTypeImpl result = schemaManager.lookupAttributeTypeRegistry( "1.1.0" );

        assertEquals( "1.3.6.1.4.1.1466.115.121.1.12", result.getSyntaxOid() );
        assertEquals( "2.5.13.1", result.getEqualityOid() );
        assertEquals( atrSize + 1, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with a superior and different USAGE
     */
    @Test
    public void testAddAttributeTypeSupDifferentUsage() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( null );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSuperiorOid( "2.5.18.4" );
        attributeType.setUsage( UsageEnum.DISTRIBUTED_OPERATION );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with itself as a superior
     */
    @Test
    public void testAddAttributeTypeSupWithOwnSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( null );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSuperiorOid( "1.1.0" );
        attributeType.setUsage( UsageEnum.DISTRIBUTED_OPERATION );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject an AttributeType with a bad superior
     */
    @Test
    public void testAddAttributeTypeSupBadSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int atrSize = schemaManager.getAttributeTypeRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableAttributeTypeImpl attributeType = new MutableAttributeTypeImpl( "1.1.0" );
        attributeType.setEqualityOid( null );
        attributeType.setOrderingOid( null );
        attributeType.setSubstringOid( null );
        attributeType.setSuperiorOid( "0.0" );
        attributeType.setUsage( UsageEnum.DISTRIBUTED_OPERATION );

        // It should fail
        assertFalse( schemaManager.add( attributeType ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isATPresent( schemaManager, "1.1.0" ) );
        assertEquals( atrSize, schemaManager.getAttributeTypeRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    //=========================================================================
    // Comparator addition tests
    //-------------------------------------------------------------------------
    @Test
    public void testAddNewComparator() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ctrSize = schemaManager.getComparatorRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractLdapComparator<?> lc = new BooleanComparator( oid );

        assertTrue( schemaManager.add( lc ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );

        assertEquals( ctrSize + 1, schemaManager.getComparatorRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        LdapComparator<?> added = schemaManager.lookupComparatorRegistry( oid );

        assertNotNull( added );
        assertEquals( lc.getClass().getName(), added.getFqcn() );
    }


    @Test
    public void testAddAlreadyExistingComparator() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ctrSize = schemaManager.getComparatorRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractLdapComparator<?> bc = new BooleanComparator( oid );

        assertTrue( schemaManager.add( bc ) );

        LdapComparator<?> added = schemaManager.lookupComparatorRegistry( oid );

        assertNotNull( added );
        assertEquals( bc.getClass().getName(), added.getFqcn() );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );
        assertEquals( ctrSize + 1, schemaManager.getComparatorRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        AbstractLdapComparator<?> lc = new CsnComparator( oid );

        assertFalse( schemaManager.add( lc ) );

        errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );

        assertEquals( ctrSize + 1, schemaManager.getComparatorRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        added = schemaManager.lookupComparatorRegistry( oid );

        assertNotNull( added );
        assertEquals( bc.getClass().getName(), added.getFqcn() );
    }


    /**
     * Test that we can't add two comparators with the same class code.
     */
    @Test
    public void testAddComparatorWithWrongFQCN() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ctrSize = schemaManager.getComparatorRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractLdapComparator<?> lc = new BooleanComparator( oid );

        // using java.sql.ResultSet cause it is very unlikely to get loaded
        // in ADS, as the FQCN is not the one expected
        lc.setFqcn( "java.sql.ResultSet" );

        assertFalse( schemaManager.add( lc ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );

        assertEquals( ctrSize, schemaManager.getComparatorRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        try
        {
            schemaManager.lookupComparatorRegistry( oid );
            fail();
        }
        catch ( Exception e )
        {
            // Expected
            assertTrue( true );
        }
    }


    //=========================================================================
    // DITContentRule addition tests
    //-------------------------------------------------------------------------
    // TODO

    //=========================================================================
    // DITStructureRule addition tests
    //-------------------------------------------------------------------------
    // TODO

    //=========================================================================
    // MatchingRule addition tests
    //-------------------------------------------------------------------------
    /**
     * Try to inject a new MatchingRule
     */
    @Test
    public void testAddValidMatchingRule() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRuleImpl matchingRule = new MutableMatchingRuleImpl( "1.1.0" );
        matchingRule.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );

        // It should not fail
        assertTrue( schemaManager.add( matchingRule ) );

        assertTrue( isMRPresent( schemaManager, "1.1.0" ) );

        // The C and N must have default values
        MatchingRule added = schemaManager.lookupMatchingRuleRegistry( "1.1.0" );

        assertEquals( NoOpNormalizer.class.getName(), added.getNormalizer().getClass().getName() );
        assertEquals( ComparableComparator.class.getName(), added.getLdapComparator().getClass().getName() );

        assertEquals( mrrSize + 1, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a new MatchingRule without a syntax
     */
    @Test
    public void testAddMatchingRuleNoSyntax() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRuleImpl matchingRule = new MutableMatchingRuleImpl( "1.1.0" );

        // It should fail (no syntax)
        assertFalse( schemaManager.add( matchingRule ) );

        List<Throwable> errors = schemaManager.getErrors();

        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );
        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isMRPresent( schemaManager, "1.1.0" ) );

        assertEquals( mrrSize, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a new MatchingRule with an existing OID
     */
    @Test
    public void testAddMatchingRuleExistingOID() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRuleImpl matchingRule = new MutableMatchingRuleImpl( "2.5.13.0" );
        matchingRule.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );

        // It should fail (oid already registered)
        assertFalse( schemaManager.add( matchingRule ) );

        List<Throwable> errors = schemaManager.getErrors();

        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );
        assertTrue( error instanceof LdapSchemaException );

        // Check that the existing MR has not been replaced
        assertTrue( isMRPresent( schemaManager, "2.5.13.0" ) );
        MutableMatchingRule existing = schemaManager.lookupMatchingRuleRegistry( "2.5.13.0" );

        assertEquals( "objectIdentifierMatch", existing.getName() );

        assertEquals( mrrSize, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a new MatchingRule with an existing name
     */
    @Test
    public void testAddMatchingRuleExistingName() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRule matchingRule = new MutableMatchingRuleImpl( "1.1.0" );
        matchingRule.setNames( "Test", "objectIdentifierMatch" );
        matchingRule.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );

        // It should fail (name already registered)
        assertFalse( schemaManager.add( matchingRule ) );

        List<Throwable> errors = schemaManager.getErrors();

        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );
        assertTrue( error instanceof LdapSchemaException );

        assertEquals( mrrSize, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a new MatchingRule with an existing AT name
     */
    @Test
    public void testAddMatchingRuleExistingATName() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRuleImpl matchingRule = new MutableMatchingRuleImpl( "1.1.0" );
        matchingRule.setNames( "Test", "cn" );
        matchingRule.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );

        // It should not fail
        assertTrue( schemaManager.add( matchingRule ) );

        List<Throwable> errors = schemaManager.getErrors();

        assertEquals( 0, errors.size() );

        // Check that the new MR has been injected
        assertTrue( isMRPresent( schemaManager, "1.1.0" ) );
        MutableMatchingRule added = schemaManager.lookupMatchingRuleRegistry( "1.1.0" );

        assertTrue( added.getNames().contains( "cn" ) );
        assertTrue( added.getNames().contains( "Test" ) );

        assertEquals( mrrSize + 1, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a new MatchingRule with a not existing Syntax
     */
    @Test
    public void testAddMatchingRuleNotExistingSyntax() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRuleImpl matchingRule = new MutableMatchingRuleImpl( "1.1.0" );
        matchingRule.setNames( "Test" );
        matchingRule.setSyntaxOid( "1.1.1" );

        // It should fail
        assertFalse( schemaManager.add( matchingRule ) );

        List<Throwable> errors = schemaManager.getErrors();

        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertEquals( mrrSize, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a new MatchingRule with an existing AT name
     */
    @Test
    public void testAddMatchingRuleNotExistingSchema() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int mrrSize = schemaManager.getMatchingRuleRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableMatchingRuleImpl matchingRule = new MutableMatchingRuleImpl( "1.1.0" );
        matchingRule.setNames( "Test" );
        matchingRule.setSyntaxOid( "1.3.6.1.4.1.1466.115.121.1.26" );
        matchingRule.setSchemaName( "bad" );

        // It should fail
        assertFalse( schemaManager.add( matchingRule ) );

        List<Throwable> errors = schemaManager.getErrors();

        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );
        assertTrue( error instanceof LdapSchemaException );

        // Check that the new MR has been injected
        assertFalse( isMRPresent( schemaManager, "1.1.0" ) );

        assertEquals( mrrSize, schemaManager.getMatchingRuleRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    //=========================================================================
    // MatchingRuleUse addition tests
    //-------------------------------------------------------------------------
    // TODO

    //=========================================================================
    // NameForm addition tests
    //-------------------------------------------------------------------------
    // TODO

    //=========================================================================
    // Normalizer addition tests
    //-------------------------------------------------------------------------
    @Test
    public void testAddNewNormalizer() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int nrSize = schemaManager.getNormalizerRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractNormalizer normalizer = new NoOpNormalizer( oid );

        assertTrue( schemaManager.add( normalizer ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );

        assertEquals( nrSize + 1, schemaManager.getNormalizerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        MutableNormalizer added = schemaManager.lookupNormalizerRegistry( oid );

        assertNotNull( added );
        assertEquals( normalizer.getClass().getName(), added.getFqcn() );
    }


    @Test
    public void testAddAlreadyExistingNormalizer() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int nrSize = schemaManager.getNormalizerRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractNormalizer normalizer = new NoOpNormalizer( oid );

        assertTrue( schemaManager.add( normalizer ) );

        MutableNormalizer added = schemaManager.lookupNormalizerRegistry( oid );

        assertNotNull( added );
        assertEquals( normalizer.getClass().getName(), added.getFqcn() );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );
        assertEquals( nrSize + 1, schemaManager.getNormalizerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        AbstractNormalizer normalizer2 = new NoOpNormalizer( oid );

        assertFalse( schemaManager.add( normalizer2 ) );

        errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );

        assertEquals( nrSize + 1, schemaManager.getNormalizerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        added = schemaManager.lookupNormalizerRegistry( oid );

        assertNotNull( added );
        assertEquals( normalizer.getClass().getName(), added.getFqcn() );
    }


    /**
     * Test that we can't add two Normalizers with the same class code.
     */
    @Test
    public void testAddNormalizerWithWrongFQCN() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int nrSize = schemaManager.getNormalizerRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        MutableNormalizer normalizer = new NoOpNormalizer( oid );

        // using java.sql.ResultSet cause it is very unlikely to get loaded
        // in ADS, as the FQCN is not the one expected
        normalizer.setFqcn( "java.sql.ResultSet" );

        assertFalse( schemaManager.add( normalizer ) );

        List<Throwable> errors = schemaManager.getErrors();
        errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );

        assertEquals( nrSize, schemaManager.getNormalizerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        try
        {
            schemaManager.lookupNormalizerRegistry( oid );
            fail();
        }
        catch ( Exception e )
        {
            // Expected
            assertTrue( true );
        }
    }


    //=========================================================================
    // ObjectClass addition tests
    //-------------------------------------------------------------------------
    //-------------------------------------------------------------------------
    // First, not defined superior
    //-------------------------------------------------------------------------
    /**
     * Addition of a valid OC
     */
    @Test
    public void testAddObjectClassNoSuperiorValid() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );

        assertTrue( schemaManager.add( objectClass ) );

        assertEquals( 0, schemaManager.getErrors().size() );

        ObjectClass added = schemaManager.lookupObjectClassRegistry( "1.1.1" );

        assertNotNull( added );

        assertEquals( ocrSize + 1, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with an existing OID
     */
    @Test
    public void testAddObjectClassNoSuperiorWithExistingOid() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "2.5.17.0" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        Throwable error = schemaManager.getErrors().get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        ObjectClass added = schemaManager.lookupObjectClassRegistry( "2.5.17.0" );

        assertNotNull( added );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with an existing OC name
     */
    @Test
    public void testAddObjectClassNoSuperiorWithExistingOCName() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.0" );
        objectClass.setNames( "Test", "referral" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        Throwable error = schemaManager.getErrors().get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.0" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with an AT name
     */
    @Test
    public void testAddObjectClassNoSuperiorWithATName() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test", "cn" );

        assertTrue( schemaManager.add( objectClass ) );

        assertEquals( 0, schemaManager.getErrors().size() );

        ObjectClass added = schemaManager.lookupObjectClassRegistry( "1.1.1" );

        assertNotNull( added );
        assertTrue( added.getNames().contains( "Test" ) );
        assertTrue( added.getNames().contains( "cn" ) );

        assertEquals( ocrSize + 1, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with not existing AT in MAY
     */
    @Test
    public void testAddObjectClassNoSuperiorNonExistingAtInMay() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.addMayAttributeTypeOids( "cn", "none", "sn" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        Throwable error = schemaManager.getErrors().get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with not existing AT in MUST
     */
    @Test
    public void testAddObjectClassNoSuperiorNonExistingAtInMust() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.addMustAttributeTypeOids( "cn", "none", "sn" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        Throwable error = schemaManager.getErrors().get( 0 );

        assertTrue( error instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with an AT present more than once in MAY
     */
    @Test
    public void testAddObjectClassNoSuperiorATMoreThanOnceInMay() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.addMayAttributeTypeOids( "cn", "ref", "commonName" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with an AT present more than once in MUST
     */
    @Test
    public void testAddObjectClassNoSuperiorATMoreThanOnceInMust() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.addMustAttributeTypeOids( "cn", "ref", "2.5.4.3" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with an AT present in MUST and MAY.
     */
    @Test
    public void testAddObjectClassNoSuperiorATInMustAndMay() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.addMustAttributeTypeOids( "cn", "ref" );
        objectClass.addMayAttributeTypeOids( "2.5.4.3" );

        // Same AT i MAY and MUST : should fail
        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with a collective AT present in MUST or MAY.
     */
    @Test
    public void testAddObjectClassNoSuperiorCollectiveATInMustOrMay() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        schemaManager.loadWithDeps( "collective" );
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        // Check a addition in MUST
        ObjectClass objectClassMust = new ObjectClass( "1.1.1" );
        objectClassMust.addMustAttributeTypeOids( "c-o", "ref" );

        // collective attribute in MUST : failure expected
        assertFalse( schemaManager.add( objectClassMust ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        // Check an addition in MAY
        ObjectClass objectClassMay = new ObjectClass( "1.1.1" );
        objectClassMay.addMayAttributeTypeOids( "c-o", "ref" );

        // collective attribute in MAY : failure expected
        assertFalse( schemaManager.add( objectClassMay ) );

        assertEquals( 1, schemaManager.getErrors().size() );
        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    //-------------------------------------------------------------------------
    // Then, with superiors
    //-------------------------------------------------------------------------
    /**
     * Addition of a valid OC with some superiors
     */
    @Test
    public void testAddObjectClassSuperiorsValid() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "alias", "referral", "top" );

        assertTrue( schemaManager.add( objectClass ) );

        assertEquals( 0, schemaManager.getErrors().size() );

        ObjectClass added = schemaManager.lookupObjectClassRegistry( "1.1.1" );

        assertNotNull( added );
        assertTrue( added.getNames().contains( "Test" ) );
        assertNotNull( added.getSuperiors() );
        assertEquals( 3, added.getSuperiors().size() );

        Set<String> expectedSups = new HashSet<String>();
        expectedSups.add( "alias" );
        expectedSups.add( "referral" );
        expectedSups.add( "top" );

        for ( ObjectClass addedOC : added.getSuperiors() )
        {
            assertTrue( expectedSups.contains( addedOC.getName() ) );
            expectedSups.remove( addedOC.getName() );
        }

        assertEquals( ocrSize + 1, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with itself in the SUP list
     */
    @Test
    public void testAddObjectClassSuperiorsWithCycle() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "alias", "Test", "referral" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with the same OC more than once in SUP
     */
    @Test
    public void testAddObjectClassSuperiorsOcMoreThanOnceInSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();
        ObjectClass objectClass = new ObjectClass( "1.1.1" );

        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "alias", "referral", "2.5.6.1" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with a non existing OC in SUP
     */
    @Test
    public void testAddObjectClassSuperiorsNonExistingOCInSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "alias", "refessal" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an ABSTRACT OC with some AUXILIARY superior
     */
    @Test
    public void testAddObjectClassSuperiorsAbstractWithAuxiliaryInSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.ABSTRACT );
        objectClass.addSuperiorOids( "extensibleObject" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an ABSTRACT OC with some STRUCTURAL superior
     */
    @Test
    public void testAddObjectClassSuperiorsAbstractWithStructuralInSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.ABSTRACT );
        objectClass.addSuperiorOids( "referral" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an AUXILIARY OC with some STRUCTURAL superior
     */
    @Test
    public void testAddObjectClassSuperiorsAuxiliaryWithStructuralInSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.AUXILIARY );
        objectClass.addSuperiorOids( "referral" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an STRUCTURAL OC with some AUXILIARY superior
     */
    @Test
    public void testAddObjectClassSuperiorsStructuralWithAuxiliaryInSup() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "extensibleObject" );

        assertFalse( schemaManager.add( objectClass ) );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with some AT present in MUST and in MAY in one of its
     * superior
     */
    @Test
    public void testAddObjectClassSuperiorsATInMustPresentInSuperiorsMay() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "alias", "OpenLDAProotDSE" );
        objectClass.addMustAttributeTypeOids( "aliasedObjectName", "cn" );

        assertTrue( schemaManager.add( objectClass ) );

        assertEquals( 0, schemaManager.getErrors().size() );

        ObjectClass added = schemaManager.lookupObjectClassRegistry( "1.1.1" );

        assertNotNull( added );
        assertTrue( added.getNames().contains( "Test" ) );
        assertNotNull( added.getSuperiors() );
        assertEquals( 2, added.getSuperiors().size() );

        Set<String> expectedSups = new HashSet<String>();
        expectedSups.add( "alias" );
        expectedSups.add( "OpenLDAProotDSE" );

        for ( ObjectClass addedOC : added.getSuperiors() )
        {
            assertTrue( expectedSups.contains( addedOC.getName() ) );
            expectedSups.remove( addedOC.getName() );
        }

        assertEquals( ocrSize + 1, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Addition of an OC with some AT present in MAY and in MUST in one of its
     * superior : not allowed
     */
    @Test
    public void testAddObjectClassSuperiorsATInMayPresentInSuperiorsMust() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int ocrSize = schemaManager.getObjectClassRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        ObjectClass objectClass = new ObjectClass( "1.1.1" );
        objectClass.setNames( "Test" );
        objectClass.setType( ObjectClassTypeEnum.STRUCTURAL );
        objectClass.addSuperiorOids( "alias", "OpenLDAProotDSE" );
        objectClass.addMayAttributeTypeOids( "aliasedObjectName", "cn" );

        assertFalse( schemaManager.add( objectClass ) );

        assertEquals( 1, schemaManager.getErrors().size() );

        assertTrue( schemaManager.getErrors().get( 0 ) instanceof LdapSchemaException );

        assertFalse( isOCPresent( schemaManager, "1.1.1" ) );

        assertEquals( ocrSize, schemaManager.getObjectClassRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    //=========================================================================
    // Syntax addition tests
    //-------------------------------------------------------------------------
    /**
     * Try to inject a new valid Syntax, with no SC : the associated SC
     * will be the default OctetString SC
     */
    @Test
    public void testAddValidSyntax() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int sSize = schemaManager.getLdapSyntaxRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableLdapSyntaxImpl syntax = new MutableLdapSyntaxImpl( "1.1.0" );

        // It should not fail
        assertTrue( schemaManager.add( syntax ) );

        MutableLdapSyntax added = schemaManager.lookupLdapSyntaxRegistry( "1.1.0" );

        assertNotNull( added );
        assertEquals( OctetStringSyntaxChecker.class.getName(), added.getSyntaxChecker().getClass().getName() );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );

        assertTrue( isSyntaxPresent( schemaManager, "1.1.0" ) );
        assertEquals( sSize + 1, schemaManager.getLdapSyntaxRegistry().size() );
        assertEquals( goidSize + 1, schemaManager.getGlobalOidRegistry().size() );
    }


    /**
     * Try to inject a Syntax with an existing OID
     */
    @Test
    public void testAddSyntaxExistingOid() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int sSize = schemaManager.getLdapSyntaxRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        MutableLdapSyntaxImpl syntax = new MutableLdapSyntaxImpl( "2.5.4.3" );

        // It should fail
        assertFalse( schemaManager.add( syntax ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );
        Throwable error = errors.get( 0 );

        assertTrue( error instanceof LdapSchemaException );
        assertEquals( sSize, schemaManager.getLdapSyntaxRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );
    }


    //=========================================================================
    // SyntaxChecker addition tests
    //-------------------------------------------------------------------------
    @Test
    public void testAddNewSyntaxChecker() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int nrSize = schemaManager.getSyntaxCheckerRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractSyntaxChecker syntaxChecker = new RegexSyntaxChecker( oid );

        assertTrue( schemaManager.add( syntaxChecker ) );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );

        assertEquals( nrSize + 1, schemaManager.getSyntaxCheckerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        SyntaxChecker added = schemaManager.lookupSyntaxCheckerRegistry( oid );

        assertNotNull( added );
        assertEquals( syntaxChecker.getClass().getName(), added.getFqcn() );
    }


    @Test
    public void testAddAlreadyExistingSyntaxChecker() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int nrSize = schemaManager.getSyntaxCheckerRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractSyntaxChecker syntaxChecker = new RegexSyntaxChecker( oid );

        assertTrue( schemaManager.add( syntaxChecker ) );

        SyntaxChecker added = schemaManager.lookupSyntaxCheckerRegistry( oid );

        assertNotNull( added );
        assertEquals( syntaxChecker.getClass().getName(), added.getFqcn() );

        List<Throwable> errors = schemaManager.getErrors();
        assertEquals( 0, errors.size() );
        assertEquals( nrSize + 1, schemaManager.getSyntaxCheckerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        AbstractSyntaxChecker syntaxChecker2 = new RegexSyntaxChecker( oid );

        assertFalse( schemaManager.add( syntaxChecker2 ) );

        errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );

        assertEquals( nrSize + 1, schemaManager.getSyntaxCheckerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        added = schemaManager.lookupSyntaxCheckerRegistry( oid );

        assertNotNull( added );
        assertEquals( syntaxChecker.getClass().getName(), added.getFqcn() );
    }


    /**
     * Test that we can't add two SyntaxCheckers with the same class code.
     */
    @Test
    public void testAddSyntaxCheckerWithWrongFQCN() throws Exception
    {
        SchemaManager schemaManager = loadSystem();
        int nrSize = schemaManager.getSyntaxCheckerRegistry().size();
        int goidSize = schemaManager.getGlobalOidRegistry().size();

        String oid = "0.0.0";
        AbstractSyntaxChecker syntaxChecker = new RegexSyntaxChecker( oid );

        // using java.sql.ResultSet cause it is very unlikely to get loaded
        // in ADS, as the FQCN is not the one expected
        syntaxChecker.setFqcn( "java.sql.ResultSet" );

        assertFalse( schemaManager.add( syntaxChecker ) );

        List<Throwable> errors = schemaManager.getErrors();
        errors = schemaManager.getErrors();
        assertEquals( 1, errors.size() );

        assertEquals( nrSize, schemaManager.getSyntaxCheckerRegistry().size() );
        assertEquals( goidSize, schemaManager.getGlobalOidRegistry().size() );

        try
        {
            schemaManager.lookupSyntaxCheckerRegistry( oid );
            fail();
        }
        catch ( Exception e )
        {
            // Expected
            assertTrue( true );
        }
    }
}
