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


import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.NamingException;

import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
import org.apache.directory.server.schema.registries.Registries;
import org.apache.directory.shared.ldap.NotImplementedException;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.AbstractEntry;
import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Value;
import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.name.LdapDNSerializer;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.util.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A default implementation of a ServerEntry which should suite most
 * use cases.
 * 
 * This class is final, it should not be extended.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$, $Date$
 */
public final class DefaultServerEntry extends AbstractEntry<AttributeType> implements ServerEntry
{
    /** Used for serialization */
    private static final long serialVersionUID = 2L;
    
    /** The logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( DefaultServerEntry.class );

    /** The AttributeType registries */
    private final transient AttributeTypeRegistry atRegistry;
    
    /** A speedup to get the ObjectClass attribute */
    private static transient AttributeType OBJECT_CLASS_AT;
    
    /** A mutex to manage synchronization*/
    private static transient Object MUTEX = new Object();


    //-------------------------------------------------------------------------
    // Helper methods
    //-------------------------------------------------------------------------
    /**
     * Returns the attributeType from an Attribute ID.
     */
    private AttributeType getAttributeType( String upId ) throws NamingException
    {
        if ( StringTools.isEmpty( StringTools.trim( upId ) ) )
        {
            String message = "The ID should not be null or empty";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
        
        return atRegistry.lookup( upId );
    }

    
    /**
     * Get the UpId if it was null.
     */
    public static String getUpId( String upId, AttributeType attributeType )
    {
        String normUpId = StringTools.trim( upId );

        if ( ( attributeType == null ) )
        {
            if ( StringTools.isEmpty( normUpId ) )
            {
                String message = "Cannot add an attribute without an ID";
                LOG.error( message );
                throw new IllegalArgumentException( message );
            }
        }
        else if ( StringTools.isEmpty( normUpId ) )
        {
            upId = attributeType.getName();
            
            if ( StringTools.isEmpty( upId ) )
            {
                upId = attributeType.getOid();
            }
        }
        
        return upId;
    }

    
    /**
     * This method is used to initialize the OBJECT_CLASS_AT attributeType.
     * 
     * We want to do it only once, so it's a synchronized method. Note that
     * the alternative would be to call the lookup() every time, but this won't
     * be very efficient, as it will get the AT from a map, which is also
     * synchronized, so here, we have a very minimal cost.
     * 
     * We can't do it once as a static part in the body of this class, because
     * the access to the registries is mandatory to get back the AttributeType.
     */
    private void initObjectClassAT( Registries registries )
    {
        try
        {
            if ( OBJECT_CLASS_AT == null )
            {
                synchronized ( MUTEX )
                {
                    OBJECT_CLASS_AT = atRegistry.lookup( SchemaConstants.OBJECT_CLASS_AT );
                }
            }
        }
        catch ( NamingException ne )
        {
            // do nothing...
        }
    }

    
    /**
     * Add a new ServerAttribute, with its upId. If the upId is null,
     * default to the AttributeType name.
     * 
     * Updates the serverAttributeMap.
     */
    private void createAttribute( String upId, AttributeType attributeType, byte[]... values ) 
    {
        ServerAttribute attribute = new DefaultServerAttribute( attributeType, values );
        attribute.setUpId( upId, attributeType );
        attributes.put( attributeType, attribute );
    }
    
    
    /**
     * Add a new ServerAttribute, with its upId. If the upId is null,
     * default to the AttributeType name.
     * 
     * Updates the serverAttributeMap.
     */
    private void createAttribute( String upId, AttributeType attributeType, String... values ) 
    {
        ServerAttribute attribute = new DefaultServerAttribute( attributeType, values );
        attribute.setUpId( upId, attributeType );
        attributes.put( attributeType, attribute );
    }
    
    
    /**
     * Add a new ServerAttribute, with its upId. If the upId is null,
     * default to the AttributeType name.
     * 
     * Updates the serverAttributeMap.
     */
    private void createAttribute( String upId, AttributeType attributeType, Value<?>... values ) 
    {
        ServerAttribute attribute = new DefaultServerAttribute( attributeType, values );
        attribute.setUpId( upId, attributeType );
        attributes.put( attributeType, attribute );
    }
    
    
    //-------------------------------------------------------------------------
    // Constructors
    //-------------------------------------------------------------------------
    /**
     * <p>
     * Creates a new instance of DefaultServerEntry.
     * </p> 
     * <p>
     * This entry <b>must</b> be initialized before being used !
     * </p>
     */
    /* no protection ! */ DefaultServerEntry()
    {
        atRegistry = null;
        dn = LdapDN.EMPTY_LDAPDN;
    }


    /**
     * <p>
     * Creates a new instance of DefaultServerEntry, with registries. 
     * </p>
     * <p>
     * No attributes will be created.
     * </p> 
     * 
     * @param registries The reference to the global registries
     */
    public DefaultServerEntry( Registries registries )
    {
        atRegistry = registries.getAttributeTypeRegistry();
        dn = LdapDN.EMPTY_LDAPDN;

        // Initialize the ObjectClass object
        initObjectClassAT( registries );
    }


    /**
     * <p>
     * Creates a new instance of DefaultServerEntry, copying 
     * another entry, which can be a ClientEntry. 
     * </p>
     * <p>
     * No attributes will be created.
     * </p> 
     * 
     * @param registries The reference to the global registries
     * @param entry the entry to copy
     */
    public DefaultServerEntry( Registries registries, Entry entry )
    {
        atRegistry = registries.getAttributeTypeRegistry();

        // Initialize the ObjectClass object
        initObjectClassAT( registries );

        // We will clone the existing entry, because it may be normalized
        if ( entry.getDn() != null )
        {
            dn = (LdapDN)entry.getDn().clone();
        }
        else
        {
            dn = LdapDN.EMPTY_LDAPDN;
        }
        
        if ( !dn.isNormalized( ) )
        {
            try
            {
                // The dn must be normalized
                dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
            }
            catch ( NamingException ne )
            {
                LOG.warn( "The DN '" + entry.getDn() + "' cannot be normalized" );
            }
        }
        
        // Init the attributes map
        attributes = new HashMap<AttributeType, EntryAttribute>( entry.size() );
        
        // and copy all the attributes
        for ( EntryAttribute attribute:entry )
        {
            try
            {
                // First get the AttributeType
                AttributeType attributeType = null;

                if ( attribute instanceof ServerAttribute )
                {
                    attributeType = ((ServerAttribute)attribute).getAttributeType();
                }
                else
                {
                    attributeType = registries.getAttributeTypeRegistry().lookup( attribute.getId() );
                }
                
                // Create a new ServerAttribute.
                EntryAttribute serverAttribute = new DefaultServerAttribute( attributeType, attribute );
                
                // And store it
                add( serverAttribute );
            }
            catch ( NamingException ne )
            {
                // Just log a warning
                LOG.warn( "The attribute '" + attribute.getId() + "' cannot be stored" );
            }
        }
    }


    /**
     * <p>
     * Creates a new instance of DefaultServerEntry, with a 
     * DN and registries. 
     * </p>
     * <p>
     * No attributes will be created.
     * </p> 
     * 
     * @param registries The reference to the global registries
     * @param dn The DN for this serverEntry. Can be null.
     */
    public DefaultServerEntry( Registries registries, LdapDN dn )
    {
        if ( dn == null )
        {
            dn = LdapDN.EMPTY_LDAPDN;
        }
        else
        {
            this.dn = dn;
        }
        
        atRegistry = registries.getAttributeTypeRegistry();

        // Initialize the ObjectClass object
        initObjectClassAT( registries );
    }


    /**
     * <p>
     * Creates a new instance of DefaultServerEntry, with a 
     * DN, registries and a list of attributeTypes. 
     * </p>
     * <p>
     * The newly created entry is fed with the list of attributeTypes. No
     * values are associated with those attributeTypes.
     * </p>
     * <p>
     * If any of the AttributeType does not exist, they it's simply discarded.
     * </p>
     * 
     * @param registries The reference to the global registries
     * @param dn The DN for this serverEntry. Can be null.
     * @param attributeTypes The list of attributes to create, without value.
     */
    public DefaultServerEntry( Registries registries, LdapDN dn, AttributeType... attributeTypes )
    {
        if ( dn == null )
        {
            dn = LdapDN.EMPTY_LDAPDN;
        }
        else
        {
            this.dn = dn;
        }

        atRegistry = registries.getAttributeTypeRegistry();

        // Initialize the ObjectClass object
        initObjectClassAT( registries );

        // Add the attributeTypes
        set( attributeTypes );
    }

    
    /**
     * <p>
     * Creates a new instance of DefaultServerEntry, with a 
     * DN, registries and an attributeType with the user provided ID. 
     * </p>
     * <p>
     * The newly created entry is fed with the given attributeType. No
     * values are associated with this attributeType.
     * </p>
     * <p>
     * If the AttributeType does not exist, they it's simply discarded.
     * </p>
     * <p>
     * We also check that the normalized upID equals the AttributeType ID
     * </p>
     * 
     * @param registries The reference to the global registries
     * @param dn The DN for this serverEntry. Can be null.
     * @param attributeType The attribute to create, without value.
     * @param upId The User Provided ID fro this AttributeType
     */
    public DefaultServerEntry( Registries registries, LdapDN dn, AttributeType attributeType, String upId )
    {
        if ( dn == null )
        {
            dn = LdapDN.EMPTY_LDAPDN;
        }
        else
        {
            this.dn = dn;
        }
        
        atRegistry = registries.getAttributeTypeRegistry();
        // Initialize the ObjectClass object

        // Initialize the ObjectClass object
        initObjectClassAT( registries );

        try
        {
            put( upId, attributeType, (String)null );
        }
        catch ( NamingException ne )
        {
            // Just discard the AttributeType
            LOG.error( "We have had an error while adding the '{}' AttributeType : {}", upId, ne.getMessage() );
        }
    }
    
    
    /**
     * Creates a new instance of DefaultServerEntry, with a 
     * DN, registries and a list of IDs. 
     * <p>
     * No attributes will be created except the ObjectClass attribute,
     * which will contains "top". 
     * <p>
     * If any of the AttributeType does not exist, they are simply discarded.
     * 
     * @param registries The reference to the global registries
     * @param dn The DN for this serverEntry. Can be null.
     * @param upIds The list of attributes to create.
     */
    public DefaultServerEntry( Registries registries, LdapDN dn, String... upIds )
    {
        if ( dn == null )
        {
            dn = LdapDN.EMPTY_LDAPDN;
        }
        else
        {
            this.dn = dn;
        }
        
        atRegistry = registries.getAttributeTypeRegistry();

        initObjectClassAT( registries );

        set( upIds );
    }

    
    /**
     * Creates a new instance of DefaultServerEntry, with a 
     * DN, registries and a list of ServerAttributes. 
     * <p>
     * No attributes will be created except the ObjectClass attribute,
     * which will contains "top". 
     * <p>
     * If any of the AttributeType does not exist, they are simply discarded.
     * 
     * @param registries The reference to the global registries
     * @param dn The DN for this serverEntry. Can be null
     * @param attributes The list of attributes to create
     */
    public DefaultServerEntry( Registries registries, LdapDN dn, ServerAttribute... attributes )
    {
        if ( dn == null )
        {
            dn = LdapDN.EMPTY_LDAPDN;
        }
        else
        {
            this.dn = dn;
        }
        
        atRegistry = registries.getAttributeTypeRegistry();

        initObjectClassAT( registries );

        for ( ServerAttribute attribute:attributes )
        {
            // Store a new ServerAttribute
            try
            {
                put( attribute );
            }
            catch ( NamingException ne )
            {
                LOG.warn( "The ServerAttribute '{}' does not exist. It has been discarded", attribute );
            }
        }
    }

    
    //-------------------------------------------------------------------------
    // API
    //-------------------------------------------------------------------------
    /**
     * <p>
     * Add an attribute (represented by its AttributeType and some binary values) into an 
     * entry.
     * </p>
     * <p> 
     * If we already have an attribute with the same values, nothing is done 
     * (duplicated values are not allowed)
     * </p>
     * <p>
     * If the value cannot be added, or if the AttributeType is null or invalid, 
     * a NamingException is thrown.
     * </p>
     *
     * @param attributeType The attribute Type.
     * @param values The list of binary values to inject. It can be empty.
     * @throws NamingException If the attribute does not exist
     */
    public void add( AttributeType attributeType, byte[]... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
        
        // ObjectClass with binary values are not allowed
        if ( attributeType.equals( OBJECT_CLASS_AT ) )
        {
            String message = "Only String values supported for objectClass attribute";
            LOG.error(  message  );
            throw new UnsupportedOperationException( message );
        }

        EntryAttribute attribute = attributes.get( attributeType );
        
        if ( attribute != null )
        {
            // This Attribute already exist, we add the values 
            // into it
            attribute.add( values );
        }
        else
        {
            // We have to create a new Attribute and set the values.
            // The upId, which is set to null, will be setup by the 
            // createAttribute method
            createAttribute( null, attributeType, values );
        }
    }


    /**
     * <p>
     * Add an attribute (represented by its AttributeType and some String values) into an 
     * entry.
     * </p>
     * <p> 
     * If we already have an attribute with public the same value, nothing is done 
     * (duplicated values are not allowed)
     * </p>
     * <p>public 
     * If the value cannot be added, or if the AttributeType is null or invalid, 
     * a NamingException is thrown.
     * </p>
     *public 
     * @param attributeType The attribute Type
     * @param values The list of binary values to inject. It can be empty
     * @throws NamingException If the attribute does not exist
     */
    public void add( AttributeType attributeType, String... values ) throws NamingException
    {    
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
        
        EntryAttribute attribute = attributes.get( attributeType );
        
        if ( attribute != null )
        {
            // This Attribute already exist, we add the values 
            // into it
            attribute.add( values );
        }
        else
        {
            // We have to create a new Attribute and set the values.
            // The upId, which is set to null, will be setup by the 
            // createAttribute method
            createAttribute( null, attributeType, values );
        }
    }

    
    /**
     * <p>
     * Add an attribute (represented by its AttributeType and some values) into an 
     * entry.
     * </p>
     * <p> 
     * If we already have an attribute with the same value, nothing is done.
     * (duplicated values are not allowed)
     * </p>
     * <p>
     * If the value cannot be added, or if the AttributeType is null or invalid, 
     * a NamingException is thrown.
     * </p>
     *
     * @param attributeType The attribute Type
     * @param values The list of binary values to inject. It can be empty
     * @throws NamingException If the attribute does not exist
     */
    public void add( AttributeType attributeType, Value<?>... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
        
        EntryAttribute attribute = attributes.get( attributeType );
    
        if ( attribute != null )
        {
            // This Attribute already exist, we add the values 
            // into it
            attribute.add( values );
        }
        else
        {
            // We have to create a new Attribute and set the values.
            // The upId, which is set to null, will be setup by the 
            // createAttribute method
            createAttribute( null, attributeType, values );
        }
    }


    /**
     * Add some EntryAttributes to the current Entry.
     *
     * @param attributes The attributes to add
     * @throws NamingException If we can't add any of the attributes
     */
    public void add( EntryAttribute... attributes ) throws NamingException
    {
        for ( EntryAttribute attribute:attributes )
        {
            ServerAttribute serverAttribute = (ServerAttribute)attribute;
            AttributeType attributeType = serverAttribute.getAttributeType();
            
            if ( this.attributes.containsKey( attributeType ) )
            {
                // We already have an attribute with the same AttributeType
                // Just add the new values into it.
                EntryAttribute oldAttribute = this.attributes.get( attributeType );
                
                for ( Value<?> value:serverAttribute )
                {
                    oldAttribute.add( value );
                }
                
                // And update the upId
                oldAttribute.setUpId( serverAttribute.getUpId() );
            }
            else
            {
                // The attributeType does not exist, add it
                this.attributes.put( attributeType, attribute );
            }
        }
    }


    /**
     * <p>
     * Add an attribute (represented by its AttributeType and some binary values) into an 
     * entry. Set the User Provider ID at the same time
     * </p>
     * <p> 
     * If we already have an attribute with the same values, nothing is done 
     * (duplicated values are not allowed)
     * </p>
     * <p>
     * If the value cannot be added, or if the AttributeType is null or invalid, 
     * a NamingException is thrown.
     * </p>
     *
     * @param upId The user provided ID for the added AttributeType
     * @param attributeType The attribute Type.
     * @param values The list of binary values to add. It can be empty.
     * @throws NamingException If the attribute does not exist
     */
    public void add( String upId, AttributeType attributeType, byte[]... values ) throws NamingException
    {
        // ObjectClass with binary values are not allowed
        if ( attributeType.equals( OBJECT_CLASS_AT ) )
        {
            String message = "Only String values supported for objectClass attribute";
            LOG.error(  message  );
            throw new UnsupportedOperationException( message );
        }

        ServerAttribute attribute = (ServerAttribute)attributes.get( attributeType );
        
        upId = getUpId( upId, attributeType );
        
        if ( attribute != null )
        {
            // This Attribute already exist, we add the values 
            // into it
            attribute.add( values );
            attribute.setUpId( upId, attributeType );
        }
        else
        {
            // We have to create a new Attribute and set the values
            // and the upId
            createAttribute( upId, attributeType, values );
        }
    }


    /**
     * <p>
     * Add an attribute (represented by its AttributeType and some values) into an 
     * entry. Set the User Provider ID at the same time
     * </p>
     * <p> 
     * If we already have an attribute with the same values, nothing is done 
     * (duplicated values are not allowed)
     * </p>
     * <p>
     * If the value cannot be added, or if the AttributeType is null or invalid, 
     * a NamingException is thrown.
     * </p>
     *
     * @param upId The user provided ID for the added AttributeType
     * @param attributeType The attribute Type.
     * @param values The list of values to add. It can be empty.
     * @throws NamingException If the attribute does not exist
     */
    public void add( String upId, AttributeType attributeType, Value<?>... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
        
        upId = getUpId( upId, attributeType );
        
        ServerAttribute attribute = (ServerAttribute)attributes.get( attributeType );
    
        if ( attribute != null )
        {
            // This Attribute already exist, we add the values 
            // into it
            attribute.add( values );
            attribute.setUpId( upId, attributeType );
        }
        else
        {
            createAttribute( upId, attributeType, values );
        }
    }

    
    /**
     * Adds a new attribute with some String values into an entry, setting
     * the User Provided ID in the same time.
     *
     * @param upId The User provided ID
     * @param attributeType The associated AttributeType
     * @param values The String values to store into the new Attribute
     * @throws NamingException 
     */
    public void add( String upId, AttributeType attributeType, String... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
        
        upId = getUpId( upId, attributeType );

        ServerAttribute attribute = (ServerAttribute)attributes.get( attributeType );
        
        if ( attribute != null )
        {
            // This Attribute already exist, we add the values 
            // into it
            attribute.add( values );
            attribute.setUpId( upId, attributeType );
        }
        else
        {
            // We have to create a new Attribute and set the values
            // and the upId
            createAttribute( upId, attributeType, values );
        }
    }


    /**                 
     * Add an attribute (represented by its ID and binary values) into an entry. 
     *
     * @param upId The attribute ID
     * @param values The list of binary values to inject. It can be empty
     * @throws NamingException If the attribute does not exist
     */
    public void add( String upId, byte[]... values ) throws NamingException
    {
        add( upId, getAttributeType( upId ), values );
    }


    /**
     * Add an attribute (represented by its ID and string values) into an entry. 
     *
     * @param upId The attribute ID
     * @param values The list of string values to inject. It can be empty
     * @throws NamingException If the attribute does not exist
     */
    public void add( String upId, String... values ) throws NamingException
    {
        add( upId, getAttributeType( upId ), values );
    }


    /**
     * Add an attribute (represented by its ID and Value values) into an entry. 
     *
     * @param upId The attribute ID
     * @param values The list of Value values to inject. It can be empty
     * @throws NamingException If the attribute does not exist
     */
    public void add( String upId, Value<?>... values ) throws NamingException
    {
        add( upId, getAttributeType( upId ), values );
    }


    /**
     * Checks if an entry contains an attribute with some given binary values.
     *
     * @param attributeType The Attribute we are looking for.
     * @param values The searched values.
     * @return <code>true</code> if all the values are found within the attribute,
     * <code>false</code> otherwise, or if the attributes does not exist.
     */
    public boolean contains( AttributeType attributeType, byte[]... values )
    {
        if ( attributeType == null )
        {
            return false;
        }
        
        EntryAttribute attribute = attributes.get( attributeType );
        
        if ( attribute != null )
        {
            return attribute.contains( values );
        }
        else
        {
            return false;
        }
    }
    
    
    /**
     * Checks if an entry contains an attribute with some given String values.
     *
     * @param attributeType The Attribute we are looking for.
     * @param values The searched values.
     * @return <code>true</code> if all the values are found within the attribute,
     * <code>false</code> otherwise, or if the attributes does not exist.
     */
    public boolean contains( AttributeType attributeType, String... values )
    {
        if ( attributeType == null )
        {
            return false;
        }

        EntryAttribute attribute = attributes.get( attributeType );
        
        if ( attribute != null )
        {
            return attribute.contains( values );
        }
        else
        {
            return false;
        }
    }
    
    
    /**
     * Checks if an entry contains an attribute with some given binary values.
     *
     * @param attributeType The Attribute we are looking for.
     * @param values The searched values.
     * @return <code>true</code> if all the values are found within the attribute,
     * <code>false</code> otherwise, or if the attributes does not exist.
     */
    public boolean contains( AttributeType attributeType, Value<?>... values )
    {
        if ( attributeType == null )
        {
            return false;
        }
        
        EntryAttribute attribute = attributes.get( attributeType );
        
        if ( attribute != null )
        {
            return attribute.contains( values );
        }
        else
        {
            return false;
        }
    }
    
    
    /**
     * <p>
     * Checks if an entry contains a list of attributes.
     * </p>
     * <p>
     * If the list is null or empty, this method will return <code>true</code>
     * if the entry has no attribute, <code>false</code> otherwise.
     * </p>
     *
     * @param attributes The Attributes to look for
     * @return <code>true</code> if all the attributes are found within 
     * the entry, <code>false</code> if at least one of them is not present.
     * @throws NamingException If the attribute does not exist
     */
    public boolean contains( EntryAttribute... attributes ) throws NamingException
    {
        for ( EntryAttribute entryAttribute:attributes )
        {
            if ( entryAttribute == null )
            {
                return this.attributes.size() == 0;
            }
            
            if ( !this.attributes.containsKey( ((ServerAttribute)entryAttribute).getAttributeType() ) )
            {
                return false;
            }
        }
        
        return true;
    }


    /**
     * Checks if an entry contains an attribute with some binary values.
     *
     * @param id The Attribute we are looking for.
     * @param values The searched values.
     * @return <code>true</code> if all the values are found within the attribute,
     * false if at least one value is not present or if the ID is not valid. 
     */
    public boolean contains( String id, byte[]... values )
    {
        if ( id == null )
        {
            return false;
        }
        
        try
        {
            AttributeType attributeType = atRegistry.lookup( id );
            
            if ( attributeType == null )
            {
                return false;
            }
            
            EntryAttribute attribute = attributes.get( attributeType );
            
            if ( attribute != null )
            {
                return attribute.contains( values );
            }
            else
            {
                return false;
            }
        }
        catch ( NamingException ne )
        {
            return false;
        }
    }
    
    
    /**
     * Checks if an entry contains an attribute with some String values.
     *
     * @param id The Attribute we are looking for.
     * @param values The searched values.
     * @return <code>true</code> if all the values are found within the attribute,
     * false if at least one value is not present or if the ID is not valid. 
     */
    public boolean contains( String id, String... values )
    {
        if ( id == null )
        {
            return false;
        }
        
        try
        {
            AttributeType attributeType = atRegistry.lookup( id );
            
            if ( attributeType == null )
            {
                return false;
            }
            
            EntryAttribute attribute = attributes.get( attributeType );
            
            if ( attribute != null )
            {
                return attribute.contains( values );
            }
            else
            {
                return false;
            }
        }
        catch ( NamingException ne )
        {
            return false;
        }
    }
    
    
    /**
     * Checks if an entry contains an attribute with some values.
     *
     * @param id The Attribute we are looking for.
     * @param values The searched values.
     * @return <code>true</code> if all the values are found within the attribute,
     * false if at least one value is not present or if the ID is not valid. 
     */
    public boolean contains( String id, Value<?>... values )
    {
        if ( id == null )
        {
            return false;
        }
        
        try
        {
            AttributeType attributeType = atRegistry.lookup( id );
            
            if ( attributeType == null )
            {
                return false;
            }

            EntryAttribute attribute = attributes.get( attributeType );
            
            if ( attribute != null )
            {
                return attribute.contains( values );
            }
            else
            {
                return false;
            }
        }
        catch ( NamingException ne )
        {
            return false;
        }
    }
    
    
    /**
     * Checks if an entry contains a specific AttributeType.
     *
     * @param attributeType The AttributeType to look for.
     * @return <code>true</code> if the attribute is found within the entry.
     */
    public boolean containsAttribute( AttributeType attributeType )
    {
        return attributes.containsKey( attributeType );
    }

    
    /**
     * Checks if an entry contains some specific attributes.
     *
     * @param attributes The Attributes to look for.
     * @return <code>true</code> if the attributes are all found within the entry.
     */
    public boolean containsAttribute( String... attributes )
    {
        for ( String attribute:attributes )
        {
            try
            {
                if ( !this.attributes.containsKey( getAttributeType( attribute ) ) )
                {
                    return false;
                }
            }
            catch ( NamingException ne )
            {
                return false;
            }
        }
        
        return true;
    }

    
    /**
     * <p>
     * Returns the attribute with the specified AttributeType. The return value
     * is <code>null</code> if no match is found.  
     * </p>
     *
     * @param attributeType The attributeType we are looking for.
     * @return the attribute associated with the AttributeType.
     */
    /**
     * Returns the attribute associated with an AttributeType
     * 
     * @param attributeType the AttributeType we are looking for
     * @return the associated attribute
     */
    public EntryAttribute get( AttributeType attributeType )
    {
        return attributes.get( attributeType );
    }


    /**
     * <p>
     * Returns the attribute with the specified alias. The return value
     * is <code>null</code> if no match is found.  
     * </p>
     * <p>An Attribute with an id different from the supplied alias may 
     * be returned: for example a call with 'cn' may in some implementations 
     * return an Attribute whose getId() field returns 'commonName'.
     * </p>
     * <p>
     * If the attributeType is not found, returns null.
     * </p>
     *
     * @param alias an aliased name of the attribute identifier
     * @return the attribute associated with the alias
     */
    public EntryAttribute get( String alias )
    {
        try
        {
            return get( atRegistry.lookup( alias ) );
        }
        catch ( NamingException ne )
        {
            String message = ne.getMessage();
            LOG.error( message );
            return null;
        }
    }


    /**
     * Gets all the attributes type
     *
     * @return The combined set of all the attributes, including ObjectClass.
     */
    public Set<AttributeType> getAttributeTypes()
    {
        return attributes.keySet();
    }
    
    
    /**
     * Tells if an entry has a specific ObjectClass value
     * 
     * @param objectClass The ObjectClass ID we want to check
     * @return <code>true</code> if the ObjectClass value is present 
     * in the ObjectClass attribute
     */
    public boolean hasObjectClass( String objectClass )
    {
        return contains( OBJECT_CLASS_AT, objectClass );
    }

    
    /**
     * Tells if an entry has a specific ObjectClass Attribute
     * 
     * @param objectClass The ObjectClass we want to check
     * @return <code>true</code> if the ObjectClass value is present 
     * in the ObjectClass attribute
     */
    public boolean hasObjectClass( EntryAttribute objectClass )
    {
        if ( objectClass == null )
        {
            return false;
        }
        
        // We have to check that we are checking the ObjectClass attributeType
        if ( ((ServerAttribute)objectClass).getAttributeType() != OBJECT_CLASS_AT )
        {
            return false;
        }
        
        EntryAttribute attribute = attributes.get( OBJECT_CLASS_AT );
        
        if ( attribute == null )
        {
            // The entry does not have an ObjectClass attribute
            return false;
        }
        
        for ( Value<?> value:objectClass )
        {
            // Loop on all the values, and check if they are present
            if ( !attribute.contains( value ) )
            {
                return false;
            }
        }
        
        return true;
    }

    
    /**
     * Fail fast check performed to determine entry consistency according to schema
     * characteristics.
     *
     * @return true if the entry, it's attributes and their values are consistent
     * with the schema
     */
    public boolean isValid()
    {
        // @TODO Implement me !
        throw new NotImplementedException();
    }


    /**
     * Check performed to determine entry consistency according to the schema
     * requirements of a particular objectClass.  The entry must be of that objectClass
     * to return true: meaning if the entry's objectClass attribute does not contain
     * the objectClass argument, then false should be returned.
     *
     * @param objectClass the objectClass to use while checking for validity
     * @return true if the entry, it's attributes and their values are consistent
     * with the objectClass
     */
    public boolean isValid( EntryAttribute objectClass )
    {
        // @TODO Implement me !
        throw new NotImplementedException();
    }


    /**
     * Check performed to determine entry consistency according to the schema
     * requirements of a particular objectClass.  The entry must be of that objectClass
     * to return true: meaning if the entry's objectClass attribute does not contain
     * the objectClass argument, then false should be returned.
     *
     * @param objectClass the objectClass to use while checking for validity
     * @return true if the entry, it's attributes and their values are consistent
     * with the objectClass
     */
    public boolean isValid( String objectClass )
    {
        // @TODO Implement me !
        throw new NotImplementedException();
    }


    /**
     * <p>
     * Places a new attribute with the supplied AttributeType and binary values 
     * into the attribute collection. 
     * </p>
     * <p>
     * If there is already an attribute with the same AttributeType, the old
     * one is removed from the collection and is returned by this method. 
     * </p>
     * <p>
     * This method provides a mechanism to put an attribute with a
     * <code>null</code> value: the value may be <code>null</code>.
     *
     * @param attributeType the type of the new attribute to be put
     * @param values the binary values of the new attribute to be put
     * @return the old attribute with the same identifier, if exists; otherwise
     * <code>null</code>
     * @throws NamingException if there are failures
     */
    public EntryAttribute put( AttributeType attributeType, byte[]... values ) throws NamingException
    {
        return put( null, attributeType, values );
    }


    /**
     * <p>
     * Places a new attribute with the supplied AttributeType and String values 
     * into the attribute collection. 
     * </p>
     * <p>
     * If there is already an attribute with the same AttributeType, the old
     * one is removed from the collection and is returned by this method. 
     * </p>
     * <p>
     * This method provides a mechanism to put an attribute with a
     * <code>null</code> value: the value may be <code>null</code>.
     *
     * @param attributeType the type of the new attribute to be put
     * @param values the String values of the new attribute to be put
     * @return the old attribute with the same identifier, if exists; otherwise
     * <code>null</code>
     * @throws NamingException if there are failures
     */
    public EntryAttribute put( AttributeType attributeType, String... values ) throws NamingException
    {
        return put( null, attributeType, values );
    }

    
    /**
     * <p>
     * Places a new attribute with the supplied AttributeType and some values 
     * into the attribute collection. 
     * </p>
     * <p>
     * If there is already an attribute with the same AttributeType, the old
     * one is removed from the collection and is returned by this method. 
     * </p>
     * <p>
     * This method provides a mechanism to put an attribute with a
     * <code>null</code> value: the value may be <code>null</code>.
     *
     * @param attributeType the type of the new attribute to be put
     * @param values the values of the new attribute to be put
     * @return the old attribute with the same identifier, if exists; otherwise
     * <code>null</code>
     * @throws NamingException if there are failures
     */
    public EntryAttribute put( AttributeType attributeType, Value<?>... values ) throws NamingException
    {
        return put( null, attributeType, values );
    }


    /**
     * <p>
     * Places attributes in the attribute collection. 
     * </p>
     * <p>If there is already an attribute with the same ID as any of the 
     * new attributes, the old ones are removed from the collection and 
     * are returned by this method. If there was no attribute with the 
     * same ID the return value is <code>null</code>.
     *</p>
     *
     * @param attributes the attributes to be put
     * @return the old attributes with the same OID, if exist; otherwise
     *         <code>null</code>
     * @exception NamingException if the operation fails
     */
    public List<EntryAttribute> put( EntryAttribute... attributes ) throws NamingException
    {
        List<EntryAttribute> previous = new ArrayList<EntryAttribute>();
        
        for ( EntryAttribute serverAttribute:attributes )
        {
            if ( serverAttribute == null )
            {
                String message = "The ServerAttribute list should not contain null elements";
                LOG.error( message );
                throw new IllegalArgumentException( message );
            }
            
            EntryAttribute removed = this.attributes.put( ((ServerAttribute)serverAttribute).getAttributeType(), serverAttribute );
            
            if ( removed != null )
            {
                previous.add( removed );
            }
        }
        
        return previous;
    }


    /**
     * <p>
     * Places a new attribute with the supplied AttributeType and some binary values 
     * into the attribute collection. 
     * </p>
     * <p>
     * The given User provided ID will be used for this new AttributeEntry.
     * </p>
     * <p>
     * If there is already an attribute with the same AttributeType, the old
     * one is removed from the collection and is returned by this method. 
     * </p>
     * <p>
     * This method provides a mechanism to put an attribute with a
     * <code>null</code> value: the value may be <code>null</code>.
     *
     * @param upId The User Provided ID to be stored into the AttributeEntry
     * @param attributeType the type of the new attribute to be put
     * @param values the binary values of the new attribute to be put
     * @return the old attribute with the same identifier, if exists; otherwise
     * <code>null</code>
     * @throws NamingException if there are failures.
     */
    public EntryAttribute put( String upId, AttributeType attributeType, byte[]... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }

        if ( !StringTools.isEmpty( upId ) )
        {
            AttributeType tempAT = getAttributeType( upId );
        
            if ( !tempAT.equals( attributeType ) )
            {
                String message = "The '" + upId + "' id is not compatible with the '" + attributeType + "' attribute type";
                LOG.error( message );
                throw new IllegalArgumentException( message );
            }
        }
        else
        {
            upId = getUpId( upId, attributeType );
        }
        
        if ( attributeType.equals( OBJECT_CLASS_AT ) )
        {
            String message = "Only String values supported for objectClass attribute";
            LOG.error( message );
            throw new UnsupportedOperationException( message );
        }

        EntryAttribute attribute = new DefaultServerAttribute( upId, attributeType, values );
        return attributes.put( attributeType, attribute );
    }


    /**
     * <p>
     * Places a new attribute with the supplied AttributeType and some String values 
     * into the attribute collection. 
     * </p>
     * <p>
     * The given User provided ID will be used for this new AttributeEntry.
     * </p>
     * <p>
     * If there is already an attribute with the same AttributeType, the old
     * one is removed from the collection and is returned by this method. 
     * </p>
     * <p>
     * This method provides a mechanism to put an attribute with a
     * <code>null</code> value: the value may be <code>null</code>.
     *
     * @param upId The User Provided ID to be stored into the AttributeEntry
     * @param attributeType the type of the new attribute to be put
     * @param values the String values of the new attribute to be put
     * @return the old attribute with the same identifier, if exists; otherwise
     * <code>null</code>
     * @throws NamingException if there are failures.
     */
    public EntryAttribute put( String upId, AttributeType attributeType, String... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            try
            {
                attributeType = getAttributeType( upId );
            }
            catch ( IllegalArgumentException iae )
            {
                String message = "The attributeType should not be null";
                LOG.error( message );
                throw new IllegalArgumentException( message );
            }
        }
        else
        {
            if ( !StringTools.isEmpty( upId ) )
            {
                AttributeType tempAT = getAttributeType( upId );
            
                if ( !tempAT.equals( attributeType ) )
                {
                    String message = "The '" + upId + "' id is not compatible with the '" + attributeType + "' attribute type";
                    LOG.error( message );
                    throw new IllegalArgumentException( message );
                }
            }
            else
            {
                upId = getUpId( upId, attributeType );
            }
        }
        
        EntryAttribute attribute = new DefaultServerAttribute( upId, attributeType, values );
        return attributes.put( attributeType, attribute );
    }


    /**
     * <p>
     * Places a new attribute with the supplied AttributeType and some values 
     * into the attribute collection. 
     * </p>
     * <p>
     * The given User provided ID will be used for this new AttributeEntry.
     * </p>
     * <p>
     * If there is already an attribute with the same AttributeType, the old
     * one is removed from the collection and is returned by this method. 
     * </p>
     * <p>
     * This method provides a mechanism to put an attribute with a
     * <code>null</code> value: the value may be <code>null</code>.
     *
     * @param upId The User Provided ID to be stored into the AttributeEntry
     * @param attributeType the type of the new attribute to be put
     * @param values the values of the new attribute to be put
     * @return the old attribute with the same identifier, if exists; otherwise
     * <code>null</code>
     * @throws NamingException if there are failures.
     */
    public EntryAttribute put( String upId, AttributeType attributeType, Value<?>... values ) throws NamingException
    {
        if ( attributeType == null )
        {
            String message = "The attributeType should not be null";
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }

        if ( !StringTools.isEmpty( upId ) )
        {
            AttributeType tempAT = getAttributeType( upId );
        
            if ( !tempAT.equals( attributeType ) )
            {
                String message = "The '" + upId + "' id is not compatible with the '" + attributeType + "' attribute type";
                LOG.error( message );
                throw new IllegalArgumentException( message );
            }
        }
        else
        {
            upId = getUpId( upId, attributeType );
        }
        
        EntryAttribute attribute = new DefaultServerAttribute( upId, attributeType, values );
        return attributes.put( attributeType, attribute );
    }


    /**
     * <p>
     * Put an attribute (represented by its ID and some binary values) into an entry. 
     * </p>
     * <p> 
     * If the attribute already exists, the previous attribute will be 
     * replaced and returned.
     * </p>
     * <p>
     * If the upId is not the ID of an existing AttributeType, an IllegalArgumentException is thrown.
     * </p>
     *
     * @param upId The attribute ID
     * @param values The list of binary values to put. It can be empty.
     * @return The replaced attribute
     */
    public EntryAttribute put( String upId, byte[]... values )
    {
        try
        {
            return put( upId, getAttributeType( upId ), values );
        }
        catch ( NamingException ne )
        {
            String message = "Error while adding values into the '" + upId + "' attribute. Error : " + 
                ne.getMessage();
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
    }


    /**
     * <p>
     * Put an attribute (represented by its ID and some String values) into an entry. 
     * </p>
     * <p> 
     * If the attribute already exists, the previous attribute will be 
     * replaced and returned.
     * </p>
     * <p>
     * If the upId is not the ID of an existing AttributeType, an IllegalArgumentException is thrown.
     * </p>
     *
     * @param upId The attribute ID
     * @param values The list of String values to put. It can be empty.
     * @return The replaced attribute
     */
    public EntryAttribute put( String upId, String... values )
    {            

        try
        {
            return put( upId, getAttributeType( upId ), values );
        }
        catch ( NamingException ne )
        {
            String message = "Error while adding values into the '" + upId + "' attribute. Error : " + 
                ne.getMessage();
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
    }


    /**
     * <p>
     * Put an attribute (represented by its ID and some values) into an entry. 
     * </p>
     * <p> 
     * If the attribute already exists, the previous attribute will be 
     * replaced and returned.
     * </p>
     * <p>
     * If the upId is not the ID of an existing AttributeType, an IllegalArgumentException is thrown.
     * </p>
     *
     * @param upId The attribute ID
     * @param values The list of values to put. It can be empty.
     * @return The replaced attribute
     */
    public EntryAttribute put( String upId, Value<?>... values )
    {
        try
        {
            return put( upId, getAttributeType( upId ), values );
        }
        catch ( NamingException ne )
        {
            String message = "Error while adding values into the '" + upId + "' attribute. Error : " + 
                ne.getMessage();
            LOG.error( message );
            throw new IllegalArgumentException( message );
        }
    }


    /**
     * <p>
     * Removes the specified binary values from an attribute.
     * </p>
     * <p>
     * If at least one value is removed, this method returns <code>true</code>.
     * </p>
     * <p>
     * If there is no more value after having removed the values, the attribute
     * will be removed too.
     * </p>
     * <p>
     * If the attribute does not exist, nothing is done and the method returns 
     * <code>false</code>
     * </p> 
     *
     * @param attributeType The attribute type  
     * @param values the values to be removed
     * @return <code>true</code> if at least a value is removed, <code>false</code>
     * if not all the values have been removed or if the attribute does not exist. 
     */
    public boolean remove( AttributeType attributeType, byte[]... values ) throws NamingException
    {
        try
        {
            EntryAttribute attribute = attributes.get( attributeType );
            
            if ( attribute == null )
            {
                // Can't remove values from a not existing attribute !
                return false;
            }
            
            int nbOldValues = attribute.size();
            
            // Remove the values
            attribute.remove( values );
            
            if ( attribute.size() == 0 )
            {
                // No mare values, remove the attribute
                attributes.remove( attributeType );
                
                return true;
            }
            
            if ( nbOldValues != attribute.size() )
            {
                // At least one value have been removed, return true.
                return true;
            }
            else
            {
                // No values have been removed, return false.
                return false;
            }
        }
        catch ( IllegalArgumentException iae )
        {
            LOG.error( "The removal of values for the missing '{}' attribute is not possible", attributeType );
            return false;
        }
    }
    
    
    /**
     * <p>
     * Removes the specified String values from an attribute.
     * </p>
     * <p>
     * If at least one value is removed, this method returns <code>true</code>.
     * </p>
     * <p>
     * If there is no more value after having removed the values, the attribute
     * will be removed too.
     * </p>
     * <p>
     * If the attribute does not exist, nothing is done and the method returns 
     * <code>false</code>
     * </p> 
     *
     * @param attributeType The attribute type  
     * @param values the values to be removed
     * @return <code>true</code> if at least a value is removed, <code>false</code>
     * if not all the values have been removed or if the attribute does not exist. 
     */
    public boolean remove( AttributeType attributeType, String... values ) throws NamingException
    {
        try
        {
            EntryAttribute attribute = attributes.get( attributeType );
            
            if ( attribute == null )
            {
                // Can't remove values from a not existing attribute !
                return false;
            }
            
            int nbOldValues = attribute.size();
            
            // Remove the values
            attribute.remove( values );
            
            if ( attribute.size() == 0 )
            {
                // No mare values, remove the attribute
                attributes.remove( attributeType );
                
                return true;
            }
            
            if ( nbOldValues != attribute.size() )
            {
                // At least one value have been removed, return true.
                return true;
            }
            else
            {
                // No values have been removed, return false.
                return false;
            }
        }
        catch ( IllegalArgumentException iae )
        {
            LOG.error( "The removal of values for the missing '{}' attribute is not possible", attributeType );
            return false;
        }
    }
    
    
    /**
     * <p>
     * Removes the specified values from an attribute.
     * </p>
     * <p>
     * If at least one value is removed, this method returns <code>true</code>.
     * </p>
     * <p>
     * If there is no more value after having removed the values, the attribute
     * will be removed too.
     * </p>
     * <p>
     * If the attribute does not exist, nothing is done and the method returns 
     * <code>false</code>
     * </p> 
     *
     * @param attributeType The attribute type  
     * @param values the values to be removed
     * @return <code>true</code> if at least a value is removed, <code>false</code>
     * if not all the values have been removed or if the attribute does not exist. 
     */
    public boolean remove( AttributeType attributeType, Value<?>... values ) throws NamingException
    {
        try
        {
            EntryAttribute attribute = attributes.get( attributeType );
            
            if ( attribute == null )
            {
                // Can't remove values from a not existing attribute !
                return false;
            }
            
            int nbOldValues = attribute.size();
            
            // Remove the values
            attribute.remove( values );
            
            if ( attribute.size() == 0 )
            {
                // No mare values, remove the attribute
                attributes.remove( attributeType );
                
                return true;
            }
            
            if ( nbOldValues != attribute.size() )
            {
                // At least one value have been removed, return true.
                return true;
            }
            else
            {
                // No values have been removed, return false.
                return false;
            }
        }
        catch ( IllegalArgumentException iae )
        {
            LOG.error( "The removal of values for the missing '{}' attribute is not possible", attributeType );
            return false;
        }
    }
    
    
    public List<EntryAttribute> remove( EntryAttribute... attributes ) throws NamingException
    {
        List<EntryAttribute> removedAttributes = new ArrayList<EntryAttribute>();
        
        for ( EntryAttribute serverAttribute:attributes )
        {
            if ( this.attributes.containsKey( ((ServerAttribute)serverAttribute).getAttributeType() ) )
            {
                this.attributes.remove( ((ServerAttribute)serverAttribute).getAttributeType() );
                removedAttributes.add( serverAttribute );
            }
        }
        
        return removedAttributes;
    }


    /**
     * <p>
     * Removes the specified binary values from an attribute.
     * </p>
     * <p>
     * If at least one value is removed, this method returns <code>true</code>.
     * </p>
     * <p>
     * If there is no more value after having removed the values, the attribute
     * will be removed too.
     * </p>
     * <p>
     * If the attribute does not exist, nothing is done and the method returns 
     * <code>false</code>
     * </p> 
     *
     * @param upId The attribute ID 
     * @param values the values to be removed
     * @return <code>true</code> if at least a value is removed, <code>false</code>
     * if not all the values have been removed or if the attribute does not exist. 
     */
    public boolean remove( String upId, byte[]... values ) throws NamingException
    {
        try
        {
            AttributeType attributeType = getAttributeType( upId );

            return remove( attributeType, values );
        }
        catch ( NamingException ne )
        {
            LOG.error( "The removal of values for the missing '{}' attribute is not possible", upId );
            return false;
        }
        catch ( IllegalArgumentException iae )
        {
            LOG.error( "The removal of values for the bad '{}' attribute is not possible", upId );
            return false;
        }
    }
    
    
    /**
     * <p>
     * Removes the specified String values from an attribute.
     * </p>
     * <p>
     * If at least one value is removed, this method returns <code>true</code>.
     * </p>
     * <p>
     * If there is no more value after having removed the values, the attribute
     * will be removed too.
     * </p>
     * <p>
     * If the attribute does not exist, nothing is done and the method returns 
     * <code>false</code>
     * </p> 
     *
     * @param upId The attribute ID 
     * @param values the values to be removed
     * @return <code>true</code> if at least a value is removed, <code>false</code>
     * if not all the values have been removed or if the attribute does not exist. 
     */
    public boolean remove( String upId, String... values ) throws NamingException
    {
        try
        {
            AttributeType attributeType = getAttributeType( upId );

            return remove( attributeType, values );
        }
        catch ( NamingException ne )
        {
            LOG.error( "The removal of values for the missing '{}' attribute is not possible", upId );
            return false;
        }
        catch ( IllegalArgumentException iae )
        {
            LOG.error( "The removal of values for the bad '{}' attribute is not possible", upId );
            return false;
        }
    }
    
    
    /**
     * <p>
     * Removes the specified Value values from an attribute.
     * </p>
     * <p>
     * If at least one value is removed, this method returns <code>true</code>.
     * </p>
     * <p>
     * If there is no more value after having removed the values, the attribute
     * will be removed too.
     * </p>
     * <p>
     * If the attribute does not exist, nothing is done and the method returns 
     * <code>false</code>
     * </p> 
     *
     * @param upId The attribute ID 
     * @param values the values to be removed
     * @return <code>true</code> if at least a value is removed, <code>false</code>
     * if not all the values have been removed or if the attribute does not exist. 
     */
    public boolean remove( String upId, Value<?>... values ) throws NamingException
    {
        try
        {
            AttributeType attributeType = getAttributeType( upId );

            return remove( attributeType, values );
        }
        catch ( NamingException ne )
        {
            LOG.error( "The removal of values for the missing '{}' attribute is not possible", upId );
            return false;
        }
        catch ( IllegalArgumentException iae )
        {
            LOG.error( "The removal of values for the bad '{}' attribute is not possible", upId );
            return false;
        }
    }
    
    
    /**
     * <p>
     * Removes the attribute with the specified AttributeTypes. 
     * </p>
     * <p>
     * The removed attribute are returned by this method. 
     * </p>
     * <p>
     * If there is no attribute with the specified AttributeTypes,
     * the return value is <code>null</code>.
     * </p>
     *
     * @param attributes the AttributeTypes to be removed
     * @return the removed attributes, if any, as a list; otherwise <code>null</code>
     */
    public List<EntryAttribute> removeAttributes( AttributeType... attributes )
    {
        if ( attributes.length == 0 )
        {
            return null;
        }
        
        List<EntryAttribute> removed = new ArrayList<EntryAttribute>( attributes.length );
        
        for ( AttributeType attributeType:attributes )
        {
            EntryAttribute attr = this.attributes.remove( attributeType );
            
            if ( attr != null )
            {
                removed.add( attr );
            }
        }
        
        if ( removed.size() == 0 )
        {
            return null;
        }
        else
        {
            return removed;
        }
    }
    
    
    /**
     * <p>
     * Removes the attribute with the specified alias. 
     * </p>
     * <p>
     * The removed attribute are returned by this method. 
     * </p>
     * <p>
     * If there is no attribute with the specified alias,
     * the return value is <code>null</code>.
     * </p>
     *
     * @param attributes an aliased name of the attribute to be removed
     * @return the removed attributes, if any, as a list; otherwise <code>null</code>
     */
    public List<EntryAttribute> removeAttributes( String... attributes )
    {
        if ( attributes.length == 0 )
        {
            return null;
        }
        
        List<EntryAttribute> removed = new ArrayList<EntryAttribute>( attributes.length );
        
        for ( String attribute:attributes )
        {
            AttributeType attributeType = null;
            
            try
            {
                attributeType = atRegistry.lookup( attribute );
            }
            catch ( NamingException ne )
            {
                String message = "The attribute '" + attribute + "' does not exist in the entry";
                LOG.warn( message );
                continue;
            }
    
            EntryAttribute attr = this.attributes.remove( attributeType );
            
            if ( attr != null )
            {
                removed.add( attr );
            }
        }
        
        if ( removed.size() == 0 )
        {
            return null;
        }
        else
        {
            return removed;
        }
    }


    /**
     * <p>
     * Put some new attributes using the attributeTypes. 
     * No value is inserted. 
     * </p>
     * <p>
     * If an existing Attribute is found, it will be replaced by an
     * empty attribute, and returned to the caller.
     * </p>
     * 
     * @param attributeTypes The AttributeTypes to add.
     * @return A list of replaced Attributes, of <code>null</code> if no attribute are removed.
     */
    public List<EntryAttribute> set( AttributeType... attributeTypes )
    {
        List<EntryAttribute> removed = new ArrayList<EntryAttribute>();
        
        // Now, loop on all the attributeType to add
        for ( AttributeType attributeType:attributeTypes )
        {
            if ( attributeType == null )
            {
                String message = "The AttributeType list should not contain null values";
                LOG.error( message );
                continue;
            }
            
            EntryAttribute attribute = attributes.put( attributeType, new DefaultServerAttribute( attributeType ) );

            if ( attribute != null )
            {
                removed.add( attribute );
            }
        }
        
        if ( removed.size() == 0 )
        {
            return null;
        }
        else
        {
            return removed;
        }
    }

    
    /**
     * <p>
     * Put some new EntryAttribute using the User Provided ID. 
     * No value is inserted. 
     * </p>
     * <p>
     * If an existing Attribute is found, it will be replaced by an
     * empty attribute, and returned to the caller.
     * </p>
     * 
     * @param upIds The user provided IDs of the AttributeTypes to add.
     * @return A list of replaced Attributes.
     */
    public List<EntryAttribute> set( String... upIds )
    {
        List<EntryAttribute> removed = new ArrayList<EntryAttribute>();
        
        for ( String upId:upIds )
        {
            // Search for the corresponding AttributeType, based on the upID 
            AttributeType attributeType = null;
            
            try
            {
                attributeType = getAttributeType( upId );
            }
            catch ( NamingException ne )
            {
                LOG.warn( "Trying to add a bad attribute type '{}', error : ", upId, ne.getMessage() );
                continue;
            }
            catch ( IllegalArgumentException iae )
            {
                LOG.warn( "Trying to add a bad attribute type '{}', error : ", upId, iae.getMessage() );
                continue;
            }
            
            EntryAttribute attribute = attributes.put( attributeType, 
                new DefaultServerAttribute( upId, attributeType ));
            
            if ( attribute != null )
            {
                removed.add( attribute );
            }
        }
        
        if ( removed.size() == 0 )
        {
            return null;
        }
        else
        {
            return removed;
        }
    }


    /**
     * Convert the ServerEntry to a ClientEntry
     *
     * @return An instance of ClientEntry
     */
    public Entry toClientEntry() throws NamingException
    {
        // Copy the DN
        Entry clientEntry = new DefaultClientEntry( dn );
        
        // Convert each attribute 
        for ( EntryAttribute serverAttribute:this )
        {
            EntryAttribute clientAttribute = ((ServerAttribute)serverAttribute).toClientAttribute();
            clientEntry.add( clientAttribute );
        }
        
        return clientEntry;
    }
    
    
    //-------------------------------------------------------------------------
    // Object methods
    //-------------------------------------------------------------------------
    /**
     * Clone an entry. All the element are duplicated, so a modification on
     * the original object won't affect the cloned object, as a modification
     * on the cloned object has no impact on the original object
     */
    public Entry clone()
    {
        // First, clone the structure
        DefaultServerEntry clone = (DefaultServerEntry)super.clone();
        
        // A serverEntry has a DN, an ObjectClass attribute
        // and many attributes.
        // Clone the DN  first.
        if ( dn != null )
        {
            clone.dn = (LdapDN)dn.clone();
        }
        
        // clone the ServerAttribute Map
        clone.attributes = (Map<AttributeType, EntryAttribute>)(((HashMap<AttributeType, EntryAttribute>)attributes).clone());
        
        // now clone all the servrAttributes
        clone.attributes.clear();
        
        for ( AttributeType key:attributes.keySet() )
        {
            EntryAttribute value = (ServerAttribute)attributes.get( key ).clone();
            clone.attributes.put( key, value );
        }
        
        // We are done !
        return clone;
    }
    

    /**
     * @see java.io.Externalizable#writeExternal(ObjectOutput)
     * 
     * We can't use this method for a ServerEntry, as we have to feed the entry
     * with an registries reference
     */
    public void writeExternal( ObjectOutput out ) throws IOException
    {
        throw new IllegalStateException( "Cannot use standard serialization for a ServerEntry" );
    }
    
    
    /**
     * Serialize a server entry.
     * 
     * The structure is the following :
     * 
     * <b>[DN]</b> : The entry DN. can be empty
     * <b>[numberAttr]</b> : the bumber of attributes. Can be 0 
     * <b>[attribute's oid]*</b> : The attribute's OID to get back 
     * the attributeType on deserialization
     * <b>[Attribute]*</b> The attribute
     * 
     * @param out the buffer in which the data will be serialized
     * @throws IOException if the serialization failed
     */
    public void serialize( ObjectOutput out ) throws IOException
    {
        // First, the DN
        // Write the DN
        LdapDNSerializer.serialize( dn, out );
        
        // Then the attributes.
        out.writeInt( attributes.size() );
        
        // Iterate through the keys. We store the Attribute
        // here, to be able to restore it in the readExternal :
        // we need access to the registries, which are not available
        // in the ServerAttribute class.
        for ( AttributeType attributeType:attributes.keySet() )
        {
            // Write the oid to be able to restore the AttributeType when deserializing
            // the attribute
            String oid = attributeType.getOid();
            
            out.writeUTF( oid );
            
            // Get the attribute
            DefaultServerAttribute attribute = (DefaultServerAttribute)attributes.get( attributeType );

            // Write the attribute
            attribute.serialize( out );
        }
    }

    
    /**
     * @see java.io.Externalizable#readExternal(ObjectInput)
     * 
     * We can't use this method for a ServerEntry, as we have to feed the entry
     * with an registries reference
     */
    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
    {
        throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" );
    }
    
    
    /**
     * Deserialize a server entry. 
     * 
     * @param in The buffer containing the serialized serverEntry
     * @throws IOException if there was a problem when deserializing
     * @throws ClassNotFoundException if we can't deserialize an expected object
     */
    public void deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
    {
        // Read the DN
        dn = LdapDNSerializer.deserialize( in );
        
        // Read the number of attributes
        int nbAttributes = in.readInt();
        
        // Read the attributes
        for ( int i = 0; i < nbAttributes; i++ )
        {
            // Read the attribute's OID
            String oid = in.readUTF();
            
            try
            {
                AttributeType attributeType = atRegistry.lookup( oid );
                
                // Create the attribute we will read
                DefaultServerAttribute attribute = new DefaultServerAttribute( attributeType );
                
                // Read the attribute
                attribute.deserialize( in );
                
                attributes.put( attributeType, attribute );
            }
            catch ( NamingException ne )
            {
                // We weren't able to find the OID. The attribute will not be added
                LOG.warn( "Cannot read the attribute as it's OID ('" + oid + "') does not exist" );
                
            }
        }
    }
    
    
    /**
    * Gets the hashCode of this ServerEntry.
    *
    * @see java.lang.Object#hashCode()
     * @return the instance's hash code 
     */
    public int hashCode()
    {
        int result = 37;
        
        result = result*17 + dn.hashCode();
        
        for ( EntryAttribute attribute:attributes.values() )
        {
            result = result*17 + attribute.hashCode();
        }

        return result;
    }

    
    /**
     * @see Object#equals(Object)
     */
    public boolean equals( Object o )
    {
        // Short circuit
        if ( this == o )
        {
            return true;
        }
        
        if ( ! ( o instanceof DefaultServerEntry ) )
        {
            return false;
        }
        
        ServerEntry other = (DefaultServerEntry)o;
        
        if ( dn == null )
        {
            if ( other.getDn() != null )
            {
                return false;
            }
        }
        else
        {
            if ( !dn.equals( other.getDn() ) )
            {
                return false;
            }
        }
        
        if ( size() != other.size() )
        {
            return false;
        }
        
        for ( EntryAttribute attribute:other )
        {
            EntryAttribute attr = attributes.get( ((ServerAttribute)attribute).getAttributeType() );
            
            if ( attr == null )
            {
                return false;
            }
            
            if ( !attribute.equals( attr ) )
            {
                return false;
            }
        }
        
        return true;
    }
        
    /**
     * @see Object#toString()
     */
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        
        sb.append( "ServerEntry\n" );
        sb.append( "    dn" );
        
        if ( dn.isNormalized() )
        {
            sb.append( "[n]" );
        }
        else
        {
            sb.append(  "[]" );
        }
        
        sb.append( ": " ).append( dn ).append( '\n' );
        
        // First dump the ObjectClass attribute
        if ( containsAttribute( OBJECT_CLASS_AT ) )
        {
            EntryAttribute objectClass = get( OBJECT_CLASS_AT );
            
            sb.append( objectClass );
        }
        
        if ( attributes.size() != 0 )
        {
            for ( EntryAttribute attribute:attributes.values() )
            {
                if ( !((ServerAttribute)attribute).getAttributeType().equals( OBJECT_CLASS_AT ) )
                {
                    sb.append( attribute );
                }
            }
        }
        
        return sb.toString();
    }
}
