/*
 *  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.api.ldap.model.ldif;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;

import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;

import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * <pre>
 *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt;
 *  &lt;ldif-content-change&gt;
 *
 *  &lt;ldif-content-change&gt; ::=
 *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
 *    &lt;ldif-attrval-record-e&gt; |
 *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
 *    &lt;ldif-attrval-record-e&gt; |
 *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt;
 *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt;
 *        &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; |
 *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt;
 *
 *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt;
 *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
 *    &lt;ldif-attrval-record-e&gt; | e
 *
 *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt;
 *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; | e
 *
 *  &lt;dn-spec&gt; ::= &quot;dn:&quot; &lt;fill&gt; &lt;safe-string&gt; | &quot;dn::&quot; &lt;fill&gt; &lt;base64-string&gt;
 *
 *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt;
 *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; | e
 *
 *  &lt;criticality&gt; ::= &quot;true&quot; | &quot;false&quot; | e
 *
 *  &lt;oid&gt; ::= '.' &lt;number&gt; &lt;oid&gt; | e
 *
 *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt;
 *  &lt;attrval-specs-e&gt; |
 *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | e
 *
 *  &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
 *
 *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; |
 *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; |
 *    &quot;:&lt;&quot; &lt;fill&gt; &lt;url&gt;
 *
 *  &lt;attributeType&gt; ::= &lt;number&gt; &lt;oid&gt; | &lt;alpha&gt; &lt;chars-e&gt;
 *
 *  &lt;options-e&gt; ::= ';' &lt;char&gt; &lt;chars-e&gt; &lt;options-e&gt; |e
 *
 *  &lt;chars-e&gt; ::= &lt;char&gt; &lt;chars-e&gt; |  e
 *
 *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;value-spec&gt;
 *  &lt;sep&gt; &lt;attrval-specs-e&gt; |
 *    &quot;delete&quot; &lt;sep&gt; |
 *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;sep&gt;
 *    &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; |
 *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt;
 *    &lt;newsuperior-e&gt; &lt;sep&gt; |
 *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt;
 *    &lt;newsuperior-e&gt; &lt;sep&gt;
 *
 *  &lt;newrdn&gt; ::= ':' &lt;fill&gt; &lt;safe-string&gt; | &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt;
 *
 *  &lt;newsuperior-e&gt; ::= &quot;newsuperior&quot; &lt;newrdn&gt; | e
 *
 *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt;
 *    &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | e
 *
 *  &lt;mod-type&gt; ::= &quot;add:&quot; | &quot;delete:&quot; | &quot;replace:&quot;
 *
 *  &lt;url&gt; ::= &lt;a Uniform Resource Locator, as defined in [6]&gt;
 *
 *
 *
 *  LEXICAL
 *  -------
 *
 *  &lt;fill&gt;           ::= ' ' &lt;fill&gt; | e
 *  &lt;char&gt;           ::= &lt;alpha&gt; | &lt;digit&gt; | '-'
 *  &lt;number&gt;         ::= &lt;digit&gt; &lt;digits&gt;
 *  &lt;0-1&gt;            ::= '0' | '1'
 *  &lt;digits&gt;         ::= &lt;digit&gt; &lt;digits&gt; | e
 *  &lt;digit&gt;          ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
 *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt;
 *  &lt;seps-e&gt;         ::= &lt;sep&gt; &lt;seps-e&gt; | e
 *  &lt;sep&gt;            ::= 0x0D 0x0A | 0x0A
 *  &lt;spaces&gt;         ::= ' ' &lt;spaces-e&gt;
 *  &lt;spaces-e&gt;       ::= ' ' &lt;spaces-e&gt; | e
 *  &lt;safe-string-e&gt;  ::= &lt;safe-string&gt; | e
 *  &lt;safe-string&gt;    ::= &lt;safe-init-char&gt; &lt;safe-chars&gt;
 *  &lt;safe-init-char&gt; ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x1F] | [0x21-0x39] | 0x3B | [0x3D-0x7F]
 *  &lt;safe-chars&gt;     ::= &lt;safe-char&gt; &lt;safe-chars&gt; | e
 *  &lt;safe-char&gt;      ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x7F]
 *  &lt;base64-string&gt;  ::= &lt;base64-char&gt; &lt;base64-chars&gt;
 *  &lt;base64-chars&gt;   ::= &lt;base64-char&gt; &lt;base64-chars&gt; | e
 *  &lt;base64-char&gt;    ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | [0x41-9x5A] | [0x61-0x7A]
 *  &lt;alpha&gt;          ::= [0x41-0x5A] | [0x61-0x7A]
 *
 *  COMMENTS
 *  --------
 *  - The ldap-oid VN is not correct in the RFC-2849. It has been changed from 1*DIGIT 0*1(&quot;.&quot; 1*DIGIT) to
 *  DIGIT+ (&quot;.&quot; DIGIT+)*
 *  - The mod-spec lacks a sep between *attrval-spec and &quot;-&quot;.
 *  - The BASE64-UTF8-STRING should be BASE64-CHAR BASE64-STRING
 *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a
 *  single space before the continued value.
 * </pre>
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class LdifAttributesReader extends LdifReader
{
    /** A logger */
    private static final Logger LOG = LoggerFactory.getLogger( LdifAttributesReader.class );


    /**
     * Constructors
     */
    public LdifAttributesReader()
    {
        super();
        lines = new ArrayList<String>();
        position = 0;
        version = DEFAULT_VERSION;
    }


    /**
     * Parse an AttributeType/AttributeValue
     *
     * @param attributes The entry where to store the value
     * @param line The line to parse
     * @param lowerLine The same line, lowercased
     * @throws LdapLdifException If anything goes wrong
     */
    private void parseAttribute( Attributes attributes, String line, String lowerLine ) throws LdapLdifException
    {
        int colonIndex = line.indexOf( ':' );

        String attributeType = lowerLine.substring( 0, colonIndex );

        // We should *not* have a Dn twice
        if ( "dn".equals( attributeType ) )
        {
            LOG.error( I18n.err( I18n.ERR_13400_ENTRY_WITH_TWO_DNS ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_13439_LDIF_ENTRY_WITH_TWO_DNS ) );
        }

        Object attributeValue = parseValue( attributeType, line, colonIndex );

        // Update the entry
        javax.naming.directory.Attribute attribute = attributes.get( attributeType );

        if ( attribute == null )
        {
            attributes.put( attributeType, attributeValue );
        }
        else
        {
            attribute.add( attributeValue );
        }
    }


    /**
     * Parse an AttributeType/AttributeValue
     *
     * @param schemaManager The SchemaManager
     * @param entry The entry where to store the value
     * @param line The line to parse
     * @param lowerLine The same line, lowercased
     * @throws LdapLdifException If anything goes wrong
     */
    private void parseEntryAttribute( SchemaManager schemaManager, Entry entry, String line, String lowerLine )
        throws LdapLdifException
    {
        int colonIndex = line.indexOf( ':' );

        String attributeName = lowerLine.substring( 0, colonIndex );
        AttributeType attributeType = null;

        // We should *not* have a Dn twice
        if ( "dn".equals( attributeName ) )
        {
            LOG.error( I18n.err( I18n.ERR_13400_ENTRY_WITH_TWO_DNS ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_13439_LDIF_ENTRY_WITH_TWO_DNS ) );
        }

        if ( schemaManager != null )
        {
            attributeType = schemaManager.getAttributeType( attributeName );

            if ( attributeType == null )
            {
                String msg = I18n.err( I18n.ERR_13475_UNKNOWN_ATTRIBUTETYPE,  attributeName );
                LOG.error( msg );
                throw new LdapLdifException( msg );
            }
        }

        Object attributeValue = parseValue( attributeName, line, colonIndex );

        // Update the entry
        Attribute attribute;

        if ( schemaManager == null )
        {
            attribute = entry.get( attributeName );
        }
        else
        {
            attribute = entry.get( attributeType );
        }

        if ( attribute == null )
        {
            if ( schemaManager == null )
            {
                if ( attributeValue instanceof String )
                {
                    entry.put( attributeName, ( String ) attributeValue );
                }
                else
                {
                    entry.put( attributeName, ( byte[] ) attributeValue );
                }
            }
            else
            {
                try
                {
                    if ( attributeValue instanceof String )
                    {
                        entry.put( attributeName, attributeType, ( String ) attributeValue );
                    }
                    else
                    {
                        entry.put( attributeName, attributeType, ( byte[] ) attributeValue );
                    }
                }
                catch ( LdapException le )
                {
                    throw new LdapLdifException( I18n.err( I18n.ERR_13460_BAD_ATTRIBUTE ), le );
                }
            }
        }
        else
        {
            try
            {
                if ( attributeValue instanceof String )
                {
                    attribute.add( ( String ) attributeValue );
                }
                else
                {
                    attribute.add( ( byte[] ) attributeValue );
                }
            }
            catch ( LdapInvalidAttributeValueException liave )
            {
                throw new LdapLdifException( liave.getMessage(), liave );
            }
        }
    }


    /**
     * Parse a ldif file. The following rules are processed :
     *
     * &lt;ldif-file&gt; ::= &lt;ldif-attrval-record&gt; &lt;ldif-attrval-records&gt; |
     * &lt;ldif-change-record&gt; &lt;ldif-change-records&gt; &lt;ldif-attrval-record&gt; ::=
     * &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt; &lt;ldif-change-record&gt; ::=
     * &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt;
     * &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
     * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
     *
     * @param schemaManager The SchemaManager
     * @return The read entry
     * @throws LdapLdifException If the entry can't be read or is invalid
     */
    private Entry parseEntry( SchemaManager schemaManager ) throws LdapLdifException
    {
        if ( ( lines == null ) || lines.isEmpty() )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_13408_END_OF_LDIF ) );
            }
            
            return null;
        }

        Entry entry = new DefaultEntry( schemaManager );

        // Now, let's iterate through the other lines
        for ( String line : lines )
        {
            // Each line could start either with an OID, an attribute type, with
            // "control:" or with "changetype:"
            String lowerLine = Strings.toLowerCaseAscii( line );

            // We have three cases :
            // 1) The first line after the Dn is a "control:" -> this is an error
            // 2) The first line after the Dn is a "changeType:" -> this is an error
            // 3) The first line after the Dn is anything else
            if ( lowerLine.startsWith( "control:" ) )
            {
                LOG.error( I18n.err( I18n.ERR_13401_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_13440_NO_CHANGE ) );
            }
            else if ( lowerLine.startsWith( "changetype:" ) )
            {
                LOG.error( I18n.err( I18n.ERR_13401_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_13440_NO_CHANGE ) );
            }
            else if ( line.indexOf( ':' ) > 0 )
            {
                parseEntryAttribute( schemaManager, entry, line, lowerLine );
            }
            else
            {
                // Invalid attribute Value
                LOG.error( I18n.err( I18n.ERR_13402_EXPECTING_ATTRIBUTE_TYPE ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_13441_BAD_ATTRIBUTE ) );
            }
        }

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_13405_READ_ATTR, entry ) );
        }

        return entry;
    }


    /**
     * Parse a ldif file. The following rules are processed :
     *
     * <pre>
     * &lt;ldif-file&gt; ::= &lt;ldif-attrval-record&gt; &lt;ldif-attrval-records&gt; |
     * &lt;ldif-change-record&gt; &lt;ldif-change-records&gt; &lt;ldif-attrval-record&gt; ::=
     * &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt; &lt;ldif-change-record&gt; ::=
     * &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt;
     * &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
     * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
     * </pre>
     * 
     * @return The read entry
     * @throws LdapLdifException If the entry can't be read or is invalid
     */
    private Attributes parseAttributes() throws LdapLdifException
    {
        if ( ( lines == null ) || lines.isEmpty() )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_13408_END_OF_LDIF ) );
            }

            return null;
        }

        Attributes attributes = new BasicAttributes( true );

        // Now, let's iterate through the other lines
        for ( String line : lines )
        {
            // Each line could start either with an OID, an attribute type, with
            // "control:" or with "changetype:"
            String lowerLine = Strings.toLowerCaseAscii( line );

            // We have three cases :
            // 1) The first line after the Dn is a "control:" -> this is an error
            // 2) The first line after the Dn is a "changeType:" -> this is an error
            // 3) The first line after the Dn is anything else
            if ( lowerLine.startsWith( "control:" ) )
            {
                LOG.error( I18n.err( I18n.ERR_13401_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_13440_NO_CHANGE ) );
            }
            else if ( lowerLine.startsWith( "changetype:" ) )
            {
                LOG.error( I18n.err( I18n.ERR_13401_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_13440_NO_CHANGE ) );
            }
            else if ( line.indexOf( ':' ) > 0 )
            {
                parseAttribute( attributes, line, lowerLine );
            }
            else
            {
                // Invalid attribute Value
                LOG.error( I18n.err( I18n.ERR_13402_EXPECTING_ATTRIBUTE_TYPE ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_13441_BAD_ATTRIBUTE ) );
            }
        }

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_13405_READ_ATTR, attributes ) );
        }

        return attributes;
    }


    /**
     * A method which parses a ldif string and returns a list of Attributes.
     *
     * @param ldif The ldif string
     * @return A list of Attributes, or an empty List
     * @throws LdapLdifException If something went wrong
     */
    public Attributes parseAttributes( String ldif ) throws LdapLdifException
    {
        lines = new ArrayList<String>();
        position = 0;

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_13407_STARTS_PARSING_LDIF ) );
        }

        if ( Strings.isEmpty( ldif ) )
        {
            return new BasicAttributes( true );
        }

        StringReader strIn = new StringReader( ldif );
        reader = new BufferedReader( strIn );

        try
        {
            readLines();

            Attributes attributes = parseAttributes();

            if ( LOG.isDebugEnabled() )
            {
                if ( attributes == null )
                {
                    LOG.debug( I18n.msg( I18n.MSG_13401_PARSED_NO_ENTRY ) );
                }
                else
                {
                    LOG.debug( I18n.msg( I18n.MSG_13402_PARSED_ONE_ENTRY ) );
                }
            }

            return attributes;
        }
        catch ( LdapLdifException ne )
        {
            LOG.error( I18n.err( I18n.ERR_13403_CANNOT_PARSE_LDIF_BUFFER, ne.getLocalizedMessage() ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_13442_ERROR_PARSING_LDIF_BUFFER ), ne );
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch ( IOException ioe )
            {
                throw new LdapLdifException( I18n.err( I18n.ERR_13450_CANNOT_CLOSE_FILE ), ioe );
            }
        }
    }


    /**
     * A method which parses a ldif string and returns an Entry.
     *
     * @param ldif The ldif string
     * @return An entry
     * @throws LdapLdifException If something went wrong
     */
    public Entry parseEntry( String ldif ) throws LdapLdifException
    {
        lines = new ArrayList<String>();
        position = 0;

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_13407_STARTS_PARSING_LDIF ) );
        }

        if ( Strings.isEmpty( ldif ) )
        {
            return new DefaultEntry();
        }

        StringReader strIn = new StringReader( ldif );
        reader = new BufferedReader( strIn );

        try
        {
            readLines();

            Entry entry = parseEntry( ( SchemaManager ) null );

            if ( LOG.isDebugEnabled() )
            {
                if ( entry == null )
                {
                    LOG.debug( I18n.msg( I18n.MSG_13401_PARSED_NO_ENTRY ) );
                }
                else
                {
                    LOG.debug( I18n.msg( I18n.MSG_13402_PARSED_ONE_ENTRY ) );
                }
            }

            return entry;
        }
        catch ( LdapLdifException ne )
        {
            LOG.error( I18n.err( I18n.ERR_13403_CANNOT_PARSE_LDIF_BUFFER, ne.getLocalizedMessage() ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_13442_ERROR_PARSING_LDIF_BUFFER ), ne );
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch ( IOException ioe )
            {
                throw new LdapLdifException( I18n.err( I18n.ERR_13450_CANNOT_CLOSE_FILE ), ioe );
            }
        }
    }


    /**
     * A method which parses a ldif string and returns an Entry.
     *
     * @param schemaManager The SchemaManager
     * @param ldif The ldif string
     * @return An entry
     * @throws LdapLdifException If something went wrong
     */
    public Entry parseEntry( SchemaManager schemaManager, String ldif ) throws LdapLdifException
    {
        lines = new ArrayList<String>();
        position = 0;

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_13407_STARTS_PARSING_LDIF ) );
        }

        if ( Strings.isEmpty( ldif ) )
        {
            return new DefaultEntry( schemaManager );
        }

        StringReader strIn = new StringReader( ldif );
        reader = new BufferedReader( strIn );

        try
        {
            readLines();

            Entry entry = parseEntry( schemaManager );

            if ( LOG.isDebugEnabled() )
            {
                if ( entry == null )
                {
                    LOG.debug( I18n.msg( I18n.MSG_13401_PARSED_NO_ENTRY ) );
                }
                else
                {
                    LOG.debug( I18n.msg( I18n.MSG_13402_PARSED_ONE_ENTRY ) );
                }

            }

            return entry;
        }
        catch ( LdapLdifException ne )
        {
            LOG.error( I18n.err( I18n.ERR_13403_CANNOT_PARSE_LDIF_BUFFER, ne.getLocalizedMessage() ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_13442_ERROR_PARSING_LDIF_BUFFER ), ne );
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch ( IOException ioe )
            {
                throw new LdapLdifException( I18n.err( I18n.ERR_13450_CANNOT_CLOSE_FILE ), ioe );
            }
        }
    }
}