/*
 *  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.server.core.shared.partition;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapNoSuchAttributeException;
import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
import org.apache.directory.api.ldap.model.exception.LdapOperationErrorException;
import org.apache.directory.api.ldap.model.exception.LdapOtherException;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.ObjectClassNode;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.AttributeTypeOptions;
import org.apache.directory.api.ldap.model.schema.UsageEnum;
import org.apache.directory.api.ldap.util.tree.DnNode;
import org.apache.directory.api.util.exception.MultiException;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.InterceptorEnum;
import org.apache.directory.server.core.api.entry.ClonedServerEntry;
import org.apache.directory.server.core.api.filtering.CursorList;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursorImpl;
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext;
import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
import org.apache.directory.server.core.api.partition.AbstractPartition;
import org.apache.directory.server.core.api.partition.Partition;
import org.apache.directory.server.core.api.partition.PartitionNexus;
import org.apache.directory.server.core.api.partition.PartitionReadTxn;
import org.apache.directory.server.core.api.partition.PartitionTxn;
import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
import org.apache.directory.server.core.api.partition.Subordinates;
import org.apache.directory.server.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A root {@link Partition} that contains all other partitions, and
 * routes all operations to the child partition that matches to its base suffixes.
 * It also provides some extended operations such as accessing rootDSE and
 * listing base suffixes.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class DefaultPartitionNexus extends AbstractPartition implements PartitionNexus
{
    /** A logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( DefaultPartitionNexus.class );

    /** the fixed id: 'NEXUS' */
    private static final String NEXUS_ID = "NEXUS";

    /** Speedup for logs */
    private static final boolean IS_DEBUG = LOG.isDebugEnabled();

    /** the vendorName string proudly set to: Apache Software Foundation*/
    private static final String ASF = "Apache Software Foundation";

    /** the read only rootDSE attributes */
    private final Entry rootDse;

    /** The DirectoryService instance */
    private DirectoryService directoryService;

    /** the partitions keyed by normalized suffix strings */
    private Map<String, Partition> partitions = new HashMap<>();

    /** A structure to hold all the partitions */
    private DnNode<Partition> partitionLookupTree = new DnNode<>();

    private final List<Modification> mods = new ArrayList<>( 2 );

    /** The cn=schema Dn */
    private Dn subschemaSubentryDn;


    /**
     * Creates the root nexus singleton of the entire system.  The root DSE has
     * several attributes that are injected into it besides those that may
     * already exist.  As partitions are added to the system more namingContexts
     * attributes are added to the rootDSE.
     *
     * @see <a href="http://www.faqs.org/rfcs/rfc3045.html">Vendor Information</a>
     * @param rootDse the root entry for the DSA
     * @throws LdapException on failure to initialize
     */
    public DefaultPartitionNexus( Entry rootDse ) throws LdapException
    {
        id = NEXUS_ID;
        suffixDn = null;

        // setup that root DSE
        this.rootDse = rootDse;

        // Add the basic informations
        rootDse.put( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, ServerDNConstants.CN_SCHEMA_DN );
        rootDse.put( SchemaConstants.SUPPORTED_LDAP_VERSION_AT, "3" );
        rootDse.put( SchemaConstants.SUPPORTED_FEATURES_AT, SchemaConstants.FEATURE_ALL_OPERATIONAL_ATTRIBUTES );
        rootDse.put( SchemaConstants.SUPPORTED_EXTENSION_AT, NoticeOfDisconnect.EXTENSION_OID );

        // Add the objectClasses
        rootDse.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );

        // Add the 'vendor' name and version infos
        rootDse.put( SchemaConstants.VENDOR_NAME_AT, ASF );

        Properties props = new Properties();

        try
        {
            props.load( getClass().getResourceAsStream( "version.properties" ) );
        }
        catch ( IOException e )
        {
            LOG.error( I18n.err( I18n.ERR_33 ) );
        }

        rootDse.put( SchemaConstants.VENDOR_VERSION_AT, props.getProperty( "apacheds.version", "UNKNOWN" ) );

        // The rootDSE uuid has been randomly created
        rootDse.put( SchemaConstants.ENTRY_UUID_AT, "f290425c-8272-4e62-8a67-92b06f38dbf5" );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void repair() throws LdapException
    {
        // Nothing to do
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected void doRepair() throws LdapException
    {
        // Nothing to do
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected void doInit() throws LdapException
    {
        // NOTE: We ignore ContextPartitionConfiguration parameter here.
        if ( !initialized )
        {
            // Add the supported controls
            Iterator<String> ctrlOidItr = directoryService.getLdapCodecService().registeredControls();

            while ( ctrlOidItr.hasNext() )
            {
                rootDse.add( SchemaConstants.SUPPORTED_CONTROL_AT, ctrlOidItr.next() );
            }

            schemaManager = directoryService.getSchemaManager();

            Value attr = rootDse.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).get();
            subschemaSubentryDn = directoryService.getDnFactory().create( attr.getValue() );

            List<Partition> initializedPartitions = new ArrayList<>();

            initializedPartitions.add( 0, directoryService.getSystemPartition() );
            addContextPartition( directoryService.getSystemPartition() );

            try
            {
                for ( Partition partition : directoryService.getPartitions() )
                {
                    addContextPartition( partition );
                    initializedPartitions.add( partition );
                }

                createContextCsnModList();

                initialized = true;
            }
            finally
            {
                if ( !initialized )
                {
                    Iterator<Partition> i = initializedPartitions.iterator();

                    while ( i.hasNext() )
                    {
                        Partition partition = i.next();
                        i.remove();

                        try
                        {
                            partition.destroy( partition.beginReadTransaction() );
                        }
                        catch ( Exception e )
                        {
                            LOG.warn( "Failed to destroy a partition: " + partition.getSuffixDn(), e );
                        }
                        finally
                        {
                            unregister( partition );
                        }
                    }
                }
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected synchronized void doDestroy( PartitionTxn partitionTxn ) 
    {
        if ( !initialized )
        {
            return;
        }

        // make sure this loop is not fail fast so all backing stores can
        // have an attempt at closing down and synching their cached entries
        for ( String suffix : new HashSet<>( this.partitions.keySet() ) )
        {
            try
            {
                removeContextPartition( suffix );
            }
            catch ( Exception e )
            {
                LOG.warn( "Failed to destroy a partition: " + suffixDn, e );
            }
        }

        initialized = false;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setId( String id )
    {
        throw new UnsupportedOperationException( I18n.err( I18n.ERR_264 ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setSuffixDn( Dn suffix )
    {
        throw new UnsupportedOperationException();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void sync() throws LdapException
    {
        MultiException errors = null;

        for ( Partition partition : this.partitions.values() )
        {
            try
            {
                partition.saveContextCsn( partition.beginReadTransaction() );
                partition.sync();
            }
            catch ( Exception e )
            {
                LOG.warn( "Failed to flush partition data out.", e );
                
                if ( errors == null )
                {
                    //noinspection ThrowableInstanceNeverThrown
                    errors = new MultiException( I18n.err( I18n.ERR_265 ) );
                }

                // @todo really need to send this info to a monitor
                errors.addThrowable( e );
            }
        }

        if ( errors != null )
        {
            throw new LdapOtherException( errors.getMessage(), errors );
        }
    }


    // ------------------------------------------------------------------------
    // DirectoryPartition Interface Method Implementations
    // ------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void add( AddOperationContext addContext ) throws LdapException
    {
        Partition partition = addContext.getPartition();
        partition.add( addContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( CompareOperationContext compareContext ) throws LdapException
    {
        Attribute attr = compareContext.getOriginalEntry().get( compareContext.getAttributeType() );

        // complain if the attribute being compared does not exist in the entry
        if ( attr == null )
        {
            throw new LdapNoSuchAttributeException();
        }

        // see first if simple match without normalization succeeds
        if ( attr.contains( compareContext.getValue() ) )
        {
            return true;
        }

        // now must apply normalization to all values (attr and in request) to compare

        /*
         * Get ahold of the normalizer for the attribute and normalize the request
         * assertion value for comparisons with normalized attribute values.  Loop
         * through all values looking for a match.
         */
        Value reqVal = compareContext.getValue();

        for ( Value value : attr )
        {
            if ( value.equals( reqVal ) )
            {
                return true;
            }
        }

        return false;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry delete( DeleteOperationContext deleteContext ) throws LdapException
    {
        Partition partition = getPartition( deleteContext.getDn() );
        return partition.delete( deleteContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
    {
        Dn dn = hasEntryContext.getDn();

        if ( IS_DEBUG )
        {
            LOG.debug( "Check if Dn '{}' exists.", dn );
        }

        if ( dn.isRootDse() )
        {
            return true;
        }

        Partition partition = getPartition( dn );

        return partition.hasEntry( hasEntryContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
    {
        Dn dn = lookupContext.getDn();

        if ( dn.getNormName().equals( subschemaSubentryDn.getNormName() ) )
        {
            return new ClonedServerEntry( rootDse.clone() );
        }

        // This is for the case we do a lookup on the rootDSE
        if ( dn.isRootDse() )
        {
            return new ClonedServerEntry( rootDse );
        }

        Partition partition = getPartition( dn );
        Entry entry = partition.lookup( lookupContext );

        if ( entry == null )
        {
            throw new LdapNoSuchObjectException( "Attempt to lookup non-existant entry: "
                + dn.getName() );
        }

        return entry;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        // Special case : if we don't have any modification to apply, just return
        if ( modifyContext.getModItems().isEmpty() )
        {
            return;
        }

        Partition partition = getPartition( modifyContext.getDn() );

        partition.modify( modifyContext );

        if ( modifyContext.isPushToEvtInterceptor() )
        {
            directoryService.getInterceptor( InterceptorEnum.EVENT_INTERCEPTOR.getName() ).modify( modifyContext );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void move( MoveOperationContext moveContext ) throws LdapException
    {
        // Get the current partition
        Partition partition = getPartition( moveContext.getDn() );

        partition.move( moveContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
    {
        Partition partition = getPartition( moveAndRenameContext.getDn() );
        partition.moveAndRename( moveAndRenameContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( RenameOperationContext renameContext ) throws LdapException
    {
        Partition partition = getPartition( renameContext.getDn() );
        partition.rename( renameContext );
    }


    private EntryFilteringCursor searchRootDse( SearchOperationContext searchContext ) throws LdapException
    {
        Set<AttributeTypeOptions> ids = searchContext.getReturningAttributes();

        // -----------------------------------------------------------
        // If nothing is asked for then we just return the entry asis.
        // We let other mechanisms filter out operational attributes.
        // -----------------------------------------------------------
        if ( ( ids == null ) || ( ids.isEmpty() ) )
        {
            return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( getRootDse( null ) ), searchContext,
                directoryService.getSchemaManager() );
        }

        // -----------------------------------------------------------
        // Collect all the real attributes besides 1.1, +, and * and
        // note if we've seen these special attributes as well.
        // -----------------------------------------------------------

        Set<String> realIds = new HashSet<>();
        boolean allUserAttributes = searchContext.isAllUserAttributes();
        boolean allOperationalAttributes = searchContext.isAllOperationalAttributes();
        boolean noAttribute = searchContext.isNoAttributes();

        for ( AttributeTypeOptions id : ids )
        {
            try
            {
                realIds.add( id.getAttributeType().getOid() );
            }
            catch ( Exception e )
            {
                realIds.add( id.getAttributeType().getName() );
            }
        }

        // return nothing
        if ( noAttribute )
        {
            Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
            return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( serverEntry ), searchContext,
                directoryService.getSchemaManager() );
        }

        // return everything
        if ( allUserAttributes && allOperationalAttributes )
        {
            Entry foundRootDse = getRootDse( null );
            return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( foundRootDse ), searchContext,
                directoryService.getSchemaManager() );
        }

        Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
        GetRootDseOperationContext getRootDseContext = new GetRootDseOperationContext( searchContext.getSession() );
        getRootDseContext.setPartition( searchContext.getPartition() );
        getRootDseContext.setTransaction( searchContext.getTransaction() );
        
        Entry foundRootDse = getRootDse( getRootDseContext );

        for ( Attribute attribute : foundRootDse )
        {
            AttributeType type = schemaManager.lookupAttributeTypeRegistry( attribute.getId() );

            if ( realIds.contains( type.getOid() )
                    || ( allUserAttributes && ( type.getUsage() == UsageEnum.USER_APPLICATIONS ) )
                    || ( allOperationalAttributes && ( type.getUsage() != UsageEnum.USER_APPLICATIONS ) ) )
            {
                serverEntry.put( attribute );
            }
        }

        return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( serverEntry ), searchContext,
            directoryService.getSchemaManager() );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
    {
        Dn baseDn = searchContext.getDn();

        // TODO since we're handling the *, and + in the EntryFilteringCursor
        // we may not need this code: we need see if this is actually the
        // case and remove this code.
        if ( baseDn.size() == 0 )
        {
            return searchFromRoot( searchContext );
        }

        // Not sure we need this code...
        if ( !baseDn.isSchemaAware() )
        {
            searchContext.setDn( new Dn( schemaManager, baseDn ) );
        }

        // Normal case : do a search on the specific partition
        Partition backend = searchContext.getPartition();

        return backend.search( searchContext );
    }


    /**
     * Do a search from the root of the DIT. We have a few use cases to consider :
     * A) The scope is OBJECT
     * If the filter is (ObjectClass = *), then this is a RootDSE fetch, otherwise, we just
     * return nothing.
     * B) The scope is ONELEVEL
     * We just return the contextEntries of all the existing partitions
     * C) The scope is SUBLEVEL :
     * In this case, we have to do a search in each of the existing partition. We will get
     * back a list of cursors and we will wrap this list in the resulting EntryFilteringCursor.
     *   
     * @param searchContext
     * @return
     * @throws LdapException
     */
    private EntryFilteringCursor searchFromRoot( SearchOperationContext searchContext )
        throws LdapException
    {
        ExprNode filter = searchContext.getFilter();

        // We are searching from the rootDSE. We have to distinguish three cases :
        // 1) The scope is OBJECT : we have to return the rootDSE entry, filtered
        // 2) The scope is ONELEVEL : we have to return all the Naming Contexts
        boolean isObjectScope = searchContext.getScope() == SearchScope.OBJECT;

        boolean isOnelevelScope = searchContext.getScope() == SearchScope.ONELEVEL;

        // test for (objectClass=*)
        boolean isSearchAll = false;

        // We have to be careful, as we may have a filter which is not a PresenceFilter
        if ( filter instanceof ObjectClassNode )
        {
            isSearchAll = true;
        }

        if ( isObjectScope )
        {
            if ( isSearchAll )
            {
                // if basedn is "", filter is "(objectclass=*)" and scope is object
                // then we have a request for the rootDSE
                return searchRootDse( searchContext );
            }
            else
            {
                // Nothing to return in this case
                return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext,
                    directoryService.getSchemaManager() );
            }
        }
        else if ( isOnelevelScope )
        {
            // Loop on all the partitions
            // We will look into all the partitions, thus we create a list of cursors. 
            List<EntryFilteringCursor> cursors = new ArrayList<>();

            for ( Partition partition : partitions.values() )
            {
                Dn contextDn = partition.getSuffixDn();
                PartitionTxn partitionTxn = partition.beginReadTransaction();
                HasEntryOperationContext hasEntryContext = new HasEntryOperationContext(
                    searchContext.getSession(), contextDn );
                hasEntryContext.setPartition( partition );
                hasEntryContext.setTransaction( partitionTxn );
                searchContext.setPartition( partition );
                searchContext.setTransaction( partitionTxn );

                // search only if the context entry exists
                if ( partition.hasEntry( hasEntryContext ) )
                {
                    searchContext.setDn( contextDn );
                    searchContext.setScope( SearchScope.OBJECT );
                    cursors.add( partition.search( searchContext ) );
                }
            }

            return new CursorList( cursors, searchContext );
        }
        else
        {
            // This is a SUBLEVEL search. We will do multiple searches and wrap
            // a CursorList into the EntryFilteringCursor
            List<EntryFilteringCursor> cursors = new ArrayList<>();

            for ( Partition partition : partitions.values() )
            {
                PartitionTxn partitionTxn = partition.beginReadTransaction();
                Dn contextDn = partition.getSuffixDn();
                HasEntryOperationContext hasEntryContext = new HasEntryOperationContext(
                    searchContext.getSession(), contextDn );
                hasEntryContext.setPartition( partition );
                hasEntryContext.setTransaction( partitionTxn );
                searchContext.setPartition( partition );
                searchContext.setTransaction( partitionTxn );

                if ( partition.hasEntry( hasEntryContext ) )
                {
                    searchContext.setDn( contextDn );
                    EntryFilteringCursor cursor = partition.search( searchContext );

                    try
                    {
                        if ( cursor.first() )
                        {
                            cursor.beforeFirst();
                            cursors.add( cursor );
                        }
                    }
                    catch ( CursorException e )
                    {
                        // Do nothing
                    }
                }
            }

            // don't feed the above Cursors' list to a BaseEntryFilteringCursor it is skipping the naming context entry of each partition
            if ( cursors.isEmpty() )
            {
                // No candidate, return an emtpy cursor
                return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext,
                    directoryService.getSchemaManager() );
            }
            else
            {
                return new CursorList( cursors, searchContext );
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void unbind( UnbindOperationContext unbindContext ) throws LdapException
    {
        Dn unbindContextDn = unbindContext.getDn();

        if ( !Dn.isNullOrEmpty( unbindContextDn ) )
        {
            Partition partition = getPartition( unbindContext.getDn() );
            partition.unbind( unbindContext );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry getRootDse( GetRootDseOperationContext getRootDseContext )
    {
        return rootDse.clone();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Value getRootDseValue( AttributeType attributeType )
    {
        return rootDse.get( attributeType ).get();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void addContextPartition( Partition partition ) throws LdapException
    {
        // Turn on default indices
        String key = partition.getSuffixDn().getNormName();

        if ( partitions.containsKey( key ) )
        {
            throw new LdapOtherException( I18n.err( I18n.ERR_263, key ) );
        }

        if ( !partition.isInitialized() )
        {
            partition.setCacheService( directoryService.getCacheService() );
            partition.initialize();
        }

        synchronized ( partitionLookupTree )
        {
            Dn partitionSuffix = partition.getSuffixDn();

            if ( partitionSuffix == null )
            {
                throw new LdapOtherException( I18n.err( I18n.ERR_267, partition.getId() ) );
            }

            partitions.put( partitionSuffix.getNormName(), partition );
            partitionLookupTree.add( partition.getSuffixDn(), partition );

            Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );

            if ( namingContexts == null )
            {
                namingContexts = new DefaultAttribute( schemaManager
                    .lookupAttributeTypeRegistry( SchemaConstants.NAMING_CONTEXTS_AT ), partitionSuffix.getName() );
                rootDse.put( namingContexts );
            }
            else
            {
                namingContexts.add( partitionSuffix.getName() );
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void removeContextPartition( String partitionDn )
        throws LdapException
    {
        // Retrieve this partition from the aprtition's table
        Partition partition = partitions.get( partitionDn );

        if ( partition == null )
        {
            String msg = I18n.err( I18n.ERR_34, partitionDn );
            LOG.error( msg );
            throw new LdapNoSuchObjectException( msg );
        }

        String partitionSuffix = partition.getSuffixDn().getNormName();

        // Retrieve the namingContexts from the RootDSE : the partition
        // suffix must be present in those namingContexts
        Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );

        if ( namingContexts != null )
        {
            Value foundNC = null;
            
            for ( Value namingContext : namingContexts )
            {
                String normalizedNC = new Dn( schemaManager, namingContext.getValue() ).getNormName();
                
                if ( partitionSuffix.equals( normalizedNC ) )
                {
                    foundNC = namingContext;
                    break;
                }
            }
            
            if ( foundNC != null )
            {
                namingContexts.remove( foundNC );
            }
            else
            {
                String msg = I18n.err( I18n.ERR_35, partitionDn );
                LOG.error( msg );
                throw new LdapNoSuchObjectException( msg );
            }
        }

        // Update the partition tree
        synchronized ( partitionLookupTree )
        {
            partitionLookupTree.remove( partition.getSuffixDn() );
        }

        partitions.remove( partitionDn );

        try
        {
            partition.destroy( partition.beginReadTransaction() );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Partition getPartition( Dn dn ) throws LdapException
    {
        Partition parent;
        
        if ( dn == null )
        {
            dn = Dn.ROOT_DSE;
        }

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( schemaManager, dn );
        }
        
        if ( dn.isRootDse() || dn.getNormName().equals( subschemaSubentryDn.getNormName() ) )
        {
            return new RootPartition( schemaManager );
        }
        
        synchronized ( partitionLookupTree )
        {
            parent = partitionLookupTree.getElement( dn );
        }

        if ( parent == null )
        {
            throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_268, dn ) );
        }
        else
        {
            return parent;
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Dn getSuffixDn( Dn dn ) throws LdapException
    {
        Partition partition = getPartition( dn );

        return partition.getSuffixDn();
    }


    /* (non-Javadoc)
     */
    @Override
    public Set<String> listSuffixes() throws LdapException
    {
        return Collections.unmodifiableSet( partitions.keySet() );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void registerSupportedExtensions( Set<String> extensionOids ) throws LdapException
    {
        Attribute supportedExtension = rootDse.get( SchemaConstants.SUPPORTED_EXTENSION_AT );

        if ( supportedExtension == null )
        {
            rootDse.put( SchemaConstants.SUPPORTED_EXTENSION_AT, ( String ) null );
            supportedExtension = rootDse.get( SchemaConstants.SUPPORTED_EXTENSION_AT );
        }

        for ( String extensionOid : extensionOids )
        {
            supportedExtension.add( extensionOid );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void registerSupportedSaslMechanisms( Set<String> supportedSaslMechanisms ) throws LdapException
    {
        Attribute supportedSaslMechanismsAt;

        supportedSaslMechanismsAt = new DefaultAttribute(
            schemaManager.lookupAttributeTypeRegistry( SchemaConstants.SUPPORTED_SASL_MECHANISMS_AT ) );

        for ( String saslMechanism : supportedSaslMechanisms )
        {
            supportedSaslMechanismsAt.add( saslMechanism );
        }

        rootDse.add( supportedSaslMechanismsAt );
    }


    /**
     * Unregisters an ContextPartition with this BackendManager.  Called for each
     * registered Backend right befor it is to be stopped.  This prevents
     * protocol server requests from reaching the Backend and effectively puts
     * the ContextPartition's naming context offline.
     *
     * Operations against the naming context should result in an LDAP BUSY
     * result code in the returnValue if the naming context is not online.
     *
     * @param partition ContextPartition component to unregister with this
     * BackendNexus.
     * @throws Exception if there are problems unregistering the partition
     */
    private void unregister( Partition partition )
    {
        Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );

        if ( namingContexts != null )
        {
            namingContexts.remove( partition.getSuffixDn().getName() );
        }

        partitions.remove( partition.getSuffixDn().getName() );
    }


    /**
     * @return the directoryService
     */
    public DirectoryService getDirectoryService()
    {
        return directoryService;
    }


    /**
     * @param directoryService the directoryService to set
     */
    public void setDirectoryService( DirectoryService directoryService )
    {
        this.directoryService = directoryService;
    }


    private void createContextCsnModList() throws LdapException
    {
        Modification contextCsnMod = new DefaultModification();
        contextCsnMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
        DefaultAttribute contextCsnAt = new DefaultAttribute( schemaManager
            .lookupAttributeTypeRegistry( SchemaConstants.CONTEXT_CSN_AT ) );
        contextCsnMod.setAttribute( contextCsnAt );

        mods.add( contextCsnMod );

        Modification timeStampMod = new DefaultModification();
        timeStampMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
        DefaultAttribute timeStampAt = new DefaultAttribute( schemaManager
            .lookupAttributeTypeRegistry( SchemaConstants.MODIFY_TIMESTAMP_AT ) );
        timeStampMod.setAttribute( timeStampAt );

        mods.add( timeStampMod );
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public String getContextCsn( PartitionTxn partitionTxn )
    {
        // nexus doesn't contain a contextCSN
        return null;
    }


    @Override
    public void saveContextCsn( PartitionTxn partitionTxn ) throws LdapException
    {
    }
    
    
    /**
     * Return the number of children and subordinates for a given entry
     *
     * @param partitionTxn The Partition transaction
     * @param entry The entry for which we want to find the subordinates
     * @return The Subordinate instance that contains the values.
     * @throws LdapException If we had an issue while processing the request
     */
    @Override
    public Subordinates getSubordinates( PartitionTxn partitionTxn, Entry entry ) throws LdapException
    {
        return new Subordinates();
    }


    @Override
    public PartitionReadTxn beginReadTransaction()
    {
        return new PartitionReadTxn();
    }


    @Override
    public PartitionWriteTxn beginWriteTransaction()
    {
        return new PartitionWriteTxn();
    }
}
