/*
 *  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.xdbm.search.impl;


import java.util.Iterator;
import java.util.regex.Pattern;

import org.apache.directory.server.core.entry.ServerAttribute;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.xdbm.Index;
import org.apache.directory.server.xdbm.IndexEntry;
import org.apache.directory.server.xdbm.Store;
import org.apache.directory.server.xdbm.search.Evaluator;
import org.apache.directory.shared.ldap.cursor.Cursor;
import org.apache.directory.shared.ldap.entry.Value;
import org.apache.directory.shared.ldap.filter.SubstringNode;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.MatchingRule;
import org.apache.directory.shared.ldap.schema.Normalizer;
import org.apache.directory.shared.ldap.schema.SchemaManager;
import org.apache.directory.shared.ldap.schema.normalizers.NoOpNormalizer;


/**
 * Evaluates substring filter assertions on an entry.
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$
 */
public class SubstringEvaluator implements Evaluator<SubstringNode, ServerEntry>
{
    /** Database used while evaluating candidates */
    private final Store<ServerEntry> db;
    
    /** Reference to the SchemaManager */
    private final SchemaManager schemaManager;

    /** The Substring expression */
    private final SubstringNode node;

    /** The regular expression generated for the SubstringNode pattern */
    private final Pattern regex;

    private final AttributeType type;

    private final Normalizer normalizer;

    private final Index<String,ServerEntry> idx;


    /**
     * Creates a new SubstringEvaluator for substring expressions.
     *
     * @param node the substring expression node
     * @param db the database this evaluator uses
     * @param registries the set of registries
     * @throws Exception if there are failures accessing resources and the db
     */
    public SubstringEvaluator( SubstringNode node, Store<ServerEntry> db, SchemaManager schemaManager ) throws Exception
    {
        this.db = db;
        this.node = node;
        this.schemaManager = schemaManager;

        String oid = schemaManager.getAttributeTypeRegistry().getOidByName( node.getAttribute() );
        type = schemaManager.lookupAttributeTypeRegistry( oid );

        MatchingRule rule = type.getSubstring();

        if ( rule == null )
        {
            rule = type.getEquality();
        }

        if ( rule != null )
        {
            normalizer = rule.getNormalizer();
        }
        else
        {
            normalizer = new NoOpNormalizer( type.getSyntaxOid() );
        }
        
        // compile the regular expression to search for a matching attribute
        regex = node.getRegex( normalizer );

        if ( db.hasUserIndexOn( node.getAttribute() ) )
        {
            //noinspection unchecked
            idx = ( Index<String,ServerEntry> ) db.getUserIndex( node.getAttribute() );
        }
        else
        {
            idx = null;
        }
    }


    public boolean evaluate( IndexEntry<?,ServerEntry> indexEntry ) throws Exception
    {

        if ( idx == null )
        {
            //noinspection unchecked
            return evaluateWithoutIndex( ( IndexEntry<String,ServerEntry> ) indexEntry );
        }
        else
        {
            return evaluateWithIndex( indexEntry );
        }
    }


    public boolean evaluate( Long id ) throws Exception
    {

        if ( idx == null )
        {
            //noinspection unchecked
            return evaluateWithoutIndex( id );
        }
        else
        {
            return evaluateWithIndex( id );
        }
    }


    public boolean evaluate( ServerEntry entry ) throws Exception
    {

        if ( idx == null )
        {
            //noinspection unchecked
            return evaluateWithoutIndex( entry );
        }
        else
        {
            return evaluateWithIndex( entry );
        }
    }


    public Pattern getPattern()
    {
        return regex;
    }


    public SubstringNode getExpression()
    {
        return node;
    }


    private boolean evaluateWithIndex( IndexEntry<?,ServerEntry> indexEntry ) throws Exception
    {
        /*
         * Note that this is using the reverse half of the index giving a
         * considerable performance improvement on this kind of operation.
         * Otherwise we would have to scan the entire index if there were
         * no reverse lookups.
         */
        Cursor<IndexEntry<String,ServerEntry>> entries = idx.reverseCursor( indexEntry.getId() );

        // cycle through the attribute values testing for a match
        while ( entries.next() )
        {
            IndexEntry rec = entries.get();

            // once match is found cleanup and return true
            if ( regex.matcher( ( String ) rec.getValue() ).matches() )
            {
                entries.close();
                return true;
            }
        }

        // we fell through so a match was not found - assertion was false.
        return false;
    }


    @SuppressWarnings( { "UnusedDeclaration" } )
    private boolean evaluateWithIndex( ServerEntry entry ) throws Exception
    {
        throw new UnsupportedOperationException( "This is too inefficient without getId() on ServerEntry" );
    }


    private boolean evaluateWithIndex( Long id ) throws Exception
    {
        /*
         * Note that this is using the reverse half of the index giving a
         * considerable performance improvement on this kind of operation.
         * Otherwise we would have to scan the entire index if there were
         * no reverse lookups.
         */
        Cursor<IndexEntry<String,ServerEntry>> entries = idx.reverseCursor( id );

        // cycle through the attribute values testing for a match
        while ( entries.next() )
        {
            IndexEntry rec = entries.get();

            // once match is found cleanup and return true
            if ( regex.matcher( ( String ) rec.getValue() ).matches() )
            {
                entries.close();
                return true;
            }
        }

        // we fell through so a match was not found - assertion was false.
        return false;
    }


    // TODO - determine if comaparator and index entry should have the Value
    // wrapper or the raw normalized value
    private boolean evaluateWithoutIndex( Long id ) throws Exception
    {
        return evaluateWithoutIndex ( db.lookup( id ) );
    }


    // TODO - determine if comaparator and index entry should have the Value
    // wrapper or the raw normalized value
    private boolean evaluateWithoutIndex( ServerEntry entry ) throws Exception
    {
        // get the attribute
        ServerAttribute attr = ( ServerAttribute ) entry.get( type );

        // if the attribute exists and the pattern matches return true
        if ( attr != null )
        {
            /*
             * Cycle through the attribute values testing normalized version
             * obtained from using the substring matching rule's normalizer.
             * The test uses the comparator obtained from the appropriate
             * substring matching rule.
             */
            for ( Value value : attr )
            {
                value.normalize( normalizer );
                String strValue = ( String ) value.getNormalizedValue();

                // Once match is found cleanup and return true
                if ( regex.matcher( strValue ).matches() )
                {
                    return true;
                }
            }

            // Fall through as we didn't find any matching value for this attribute.
            // We will have to check in the potential descendant, if any.
        }

        // If we do not have the attribute, loop through the descendant
        // May be the node Attribute has descendant ?
        if ( schemaManager.getAttributeTypeRegistry().hasDescendants( node.getAttribute() ) )
        {
            // TODO check to see if descendant handling is necessary for the
            // index so we can match properly even when for example a name
            // attribute is used instead of more specific commonName
            Iterator<AttributeType> descendants =
                schemaManager.getAttributeTypeRegistry().descendants( node.getAttribute() );

            while ( descendants.hasNext() )
            {
                AttributeType descendant = descendants.next();

                attr = ( ServerAttribute ) entry.get( descendant );

                if ( null != attr )
                {


                    /*
                     * Cycle through the attribute values testing normalized version
                     * obtained from using the substring matching rule's normalizer.
                     * The test uses the comparator obtained from the appropriate
                     * substring matching rule.
                     */
                    for ( Value value : attr )
                    {
                        value.normalize( normalizer );
                        String strValue = ( String ) value.getNormalizedValue();

                        // Once match is found cleanup and return true
                        if ( regex.matcher( strValue ).matches() )
                        {
                            return true;
                        }
                    }
                }
            }
        }

        // we fell through so a match was not found - assertion was false.
        return false;
    }


    // TODO - determine if comaparator and index entry should have the Value
    // wrapper or the raw normalized value
    private boolean evaluateWithoutIndex( IndexEntry<String,ServerEntry> indexEntry ) throws Exception
    {
        ServerEntry entry = indexEntry.getObject();

        // resuscitate the entry if it has not been and set entry in IndexEntry
        if ( null == entry )
        {
            entry = db.lookup( indexEntry.getId() );
            indexEntry.setObject( entry );
        }

        /*
         * Don't make a call here to evaluateWithoutIndex( ServerEntry ) for
         * code reuse since we do want to set the value on the indexEntry on
         * matches.
         */

        // get the attribute
        ServerAttribute attr = ( ServerAttribute ) entry.get( type );

        // if the attribute exists and the pattern matches return true
        if ( attr != null )
        {
            /*
             * Cycle through the attribute values testing normalized version
             * obtained from using the substring matching rule's normalizer.
             * The test uses the comparator obtained from the appropriate
             * substring matching rule.
             */
            for ( Value value : attr )
            {
                value.normalize( normalizer );
                String strValue = ( String ) value.getNormalizedValue();

                // Once match is found cleanup and return true
                if ( regex.matcher( strValue ).matches() )
                {
                    // before returning we set the normalized value
                    indexEntry.setValue( strValue );
                    return true;
                }
            }

            // Fall through as we didn't find any matching value for this attribute.
            // We will have to check in the potential descendant, if any.
        }

        // If we do not have the attribute, loop through the descendant
        // May be the node Attribute has descendant ?
        if ( schemaManager.getAttributeTypeRegistry().hasDescendants( node.getAttribute() ) )
        {
            // TODO check to see if descendant handling is necessary for the
            // index so we can match properly even when for example a name
            // attribute is used instead of more specific commonName
            Iterator<AttributeType> descendants =
                schemaManager.getAttributeTypeRegistry().descendants( node.getAttribute() );

            while ( descendants.hasNext() )
            {
                AttributeType descendant = descendants.next();

                attr = ( ServerAttribute ) entry.get( descendant );

                if ( null != attr )
                {


                    /*
                     * Cycle through the attribute values testing normalized version
                     * obtained from using the substring matching rule's normalizer.
                     * The test uses the comparator obtained from the appropriate
                     * substring matching rule.
                     */
                    for ( Value value : attr )
                    {
                        value.normalize( normalizer );
                        String strValue = ( String ) value.getNormalizedValue();

                        // Once match is found cleanup and return true
                        if ( regex.matcher( strValue ).matches() )
                        {
                            // before returning we set the normalized value
                            indexEntry.setValue( strValue );
                            return true;
                        }
                    }
                }
            }
        }

        // we fell through so a match was not found - assertion was false.
        return false;
    }
}