/*
 *  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()
    {
        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 ( attributeType.equals( "dn" ) )
        {
            LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
        }

        Object attributeValue = parseValue( 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 ( attributeName.equals( "dn" ) )
        {
            LOG.error( I18n.err( I18n.ERR_12002_ENTRY_WITH_TWO_DNS ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_12003_LDIF_ENTRY_WITH_TWO_DNS ) );
        }

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

            if ( attributeType == null )
            {
                LOG.error( "" );
                throw new LdapLdifException( "" );
            }
        }

        Object attributeValue = parseValue( line, colonIndex );

        // Update the entry
        Attribute attribute = null;

        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_12057_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.size() == 0 ) )
        {
            LOG.debug( "The entry is empty : end of ldif file" );
            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.toLowerCase( 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_12004_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
            }
            else if ( lowerLine.startsWith( "changetype:" ) )
            {
                LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
            }
            else if ( line.indexOf( ':' ) > 0 )
            {
                parseEntryAttribute( schemaManager, entry, line, lowerLine );
            }
            else
            {
                // Invalid attribute Value
                LOG.error( I18n.err( I18n.ERR_12006_EXPECTING_ATTRIBUTE_TYPE ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_12007_BAD_ATTRIBUTE ) );
            }
        }

        LOG.debug( "Read an attributes : {}", entry );

        return entry;
    }


    /**
     * 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;
     *
     * @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.size() == 0 ) )
        {
            LOG.debug( "The entry is empty : end of ldif file" );
            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.toLowerCase( 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_12004_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
            }
            else if ( lowerLine.startsWith( "changetype:" ) )
            {
                LOG.error( I18n.err( I18n.ERR_12004_CHANGE_NOT_ALLOWED ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_12005_NO_CHANGE ) );
            }
            else if ( line.indexOf( ':' ) > 0 )
            {
                parseAttribute( attributes, line, lowerLine );
            }
            else
            {
                // Invalid attribute Value
                LOG.error( I18n.err( I18n.ERR_12006_EXPECTING_ATTRIBUTE_TYPE ) );
                throw new LdapLdifException( I18n.err( I18n.ERR_12007_BAD_ATTRIBUTE ) );
            }
        }

        LOG.debug( "Read an attributes : {}", 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;

        LOG.debug( "Starts parsing ldif buffer" );

        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( "Parsed no entry." );
                }
                else
                {
                    LOG.debug( "Parsed one entry." );
                }
            }

            return attributes;
        }
        catch ( LdapLdifException ne )
        {
            LOG.error( I18n.err( I18n.ERR_12008_CANNOT_PARSE_LDIF_BUFFER, ne.getLocalizedMessage() ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_12009_ERROR_PARSING_LDIF_BUFFER ), ne );
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch ( IOException ioe )
            {
                throw new LdapLdifException( I18n.err( I18n.ERR_12024_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;

        LOG.debug( "Starts parsing ldif buffer" );

        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( "Parsed no entry." );
                }
                else
                {
                    LOG.debug( "Parsed one entry." );
                }

            }

            return entry;
        }
        catch ( LdapLdifException ne )
        {
            LOG.error( I18n.err( I18n.ERR_12008_CANNOT_PARSE_LDIF_BUFFER, ne.getLocalizedMessage() ) );
            throw new LdapLdifException( I18n.err( I18n.ERR_12009_ERROR_PARSING_LDIF_BUFFER ), ne );
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch ( IOException ioe )
            {
                throw new LdapLdifException( I18n.err( I18n.ERR_12024_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;

        LOG.debug( "Starts parsing ldif buffer" );

        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( "Parsed no entry." );
                }
                else
                {
                    LOG.debug( "Parsed one entry." );
                }

            }

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