/*
 *  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.partition.impl.btree;


import java.util.Comparator;
import java.util.Iterator;

import javax.naming.NamingException;

import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.schema.registries.Registries;
import org.apache.directory.shared.ldap.NotImplementedException;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Value;
import org.apache.directory.shared.ldap.filter.ApproximateNode;
import org.apache.directory.shared.ldap.filter.EqualityNode;
import org.apache.directory.shared.ldap.filter.ExprNode;
import org.apache.directory.shared.ldap.filter.ExtensibleNode;
import org.apache.directory.shared.ldap.filter.GreaterEqNode;
import org.apache.directory.shared.ldap.filter.LessEqNode;
import org.apache.directory.shared.ldap.filter.PresenceNode;
import org.apache.directory.shared.ldap.filter.ScopeNode;
import org.apache.directory.shared.ldap.filter.SimpleNode;
import org.apache.directory.shared.ldap.filter.SubstringNode;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.ByteArrayComparator;
import org.apache.directory.shared.ldap.schema.MatchingRule;
import org.apache.directory.shared.ldap.schema.NoOpNormalizer;
import org.apache.directory.shared.ldap.schema.Normalizer;


/**
 * Evaluates LeafNode assertions on candidates using a database.
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$
 */
public class LeafEvaluator implements Evaluator
{
    /** equality matching type constant */
    private static final int EQUALITY_MATCH = 0;

    /** ordering matching type constant */
    private static final int ORDERING_MATCH = 1;

    /** substring matching type constant */
    private static final int SUBSTRING_MATCH = 2;

    /** Database used to evaluate leaf with */
    private BTreePartition db;

    /** Oid Registry used to translate attributeIds to OIDs */
    private Registries registries;

    /** Substring node evaluator we depend on */
    private SubstringEvaluator substringEvaluator;

    /** ScopeNode evaluator we depend on */
    private ScopeEvaluator scopeEvaluator;


    /**
     * Creates a leaf expression node evaluator.
     *
     * @param db
     * @param scopeEvaluator
     * @param substringEvaluator
     */
    public LeafEvaluator( BTreePartition db, Registries registries,
        ScopeEvaluator scopeEvaluator, SubstringEvaluator substringEvaluator )
    {
        this.db = db;
        this.registries = registries;
        this.scopeEvaluator = scopeEvaluator;
        this.substringEvaluator = substringEvaluator;
    }


    public ScopeEvaluator getScopeEvaluator()
    {
        return scopeEvaluator;
    }


    public SubstringEvaluator getSubstringEvaluator()
    {
        return substringEvaluator;
    }


    /**
     * Match a filter value against an entry's attribute. An entry's attribute
     * may have more than one value, and the values may not be normalized. 
     * @param node
     * @param attr
     * @param type
     * @param normalizer
     * @param comparator
     * @return
     * @throws NamingException
     */
    private boolean matchValue( SimpleNode node, EntryAttribute attr, AttributeType type, Normalizer normalizer,
        Comparator comparator ) throws NamingException
    {
        // get the normalized AVA filter value
        Value<?> filterValue = node.getValue();

        // Check if the attribute normalized value match 
        // Fast check. If it succeeds, we are done.
        if ( attr.contains( filterValue ) )
        {
            // We are lucky.
            return true;
        }

        /*
         * We need to now iterate through all values because we could not get
         * a lookup to work.  For each value we normalize and use the comparator
         * to determine if a match exists.
         */
        for ( Value<?> value:attr )
        {
            Object normValue = normalizer.normalize( value.get() );

            // TODO Fix DIRSERVER-832
            if ( 0 == comparator.compare( normValue, filterValue.get() ) )
            {
                // The value has been found. get out.
                return true;
            }
        }

        // no match so return false
        return false;
    }


    /**
     * Get the entry from the backend, if it's not already into the record
     */
    private ServerEntry getEntry( IndexRecord rec ) throws NamingException
    {
        // get the attributes associated with the entry 
        ServerEntry entry = rec.getEntry();

        // resuscitate entry if need be
        // TODO Is this really needed ? 
        // How possibly can't we have the entry at this point ?
        if ( null == entry )
        {
            rec.setEntry( db.lookup( ( Long ) rec.getEntryId() ) );
            entry = rec.getEntry();
        }

        return entry;
    }


    /**
     * @see org.apache.directory.server.core.partition.impl.btree.Evaluator#evaluate(ExprNode, IndexRecord)
     */
    public boolean evaluate( ExprNode node, IndexRecord record ) throws NamingException
    {
        if ( node instanceof ScopeNode )
        {
            return scopeEvaluator.evaluate( node, record );
        }

        if ( node instanceof PresenceNode )
        {
            String attrId = ( ( PresenceNode ) node ).getAttribute();
            return evalPresence( attrId, record );
        }
        else if ( node instanceof EqualityNode )
        {
            return evalEquality( ( EqualityNode ) node, record );
        }
        else if ( node instanceof GreaterEqNode )
        {
            return evalGreaterOrLesser( ( SimpleNode ) node, record, SimpleNode.EVAL_GREATER );
        }
        else if ( node instanceof LessEqNode )
        {
            return evalGreaterOrLesser( ( SimpleNode ) node, record, SimpleNode.EVAL_LESSER );
        }
        else if ( node instanceof SubstringNode )
        {
            return substringEvaluator.evaluate( node, record );
        }
        else if ( node instanceof ExtensibleNode )
        {
            throw new NotImplementedException();
        }
        else if ( node instanceof ApproximateNode )
        {
            return evalEquality( ( ApproximateNode ) node, record );
        }
        else
        {
            throw new NamingException( "Unrecognized leaf node type: " + node );
        }
    }


    /**
     * Evaluates a simple greater than or less than attribute value assertion on
     * a perspective candidate.
     * 
     * @param node the greater than or less than node to evaluate
     * @param record the IndexRecord of the perspective candidate
     * @param isGreaterOrLesser true if it is a greater than or equal to comparison,
     *      false if it is a less than or equal to comparison.
     * @return the ava evaluation on the perspective candidate
     * @throws NamingException if there is a database access failure
     */
    private boolean evalGreaterOrLesser( SimpleNode node, IndexRecord record, boolean isGreaterOrLesser )
        throws NamingException
    {
        String attrId = node.getAttribute();
        long id = ( Long ) record.getEntryId();

        if ( db.hasUserIndexOn( attrId ) )
        {
            Index idx = db.getUserIndex( attrId );

            if ( isGreaterOrLesser = SimpleNode.EVAL_GREATER )
            {
                if ( idx.hasValue( node.getValue(), id, SimpleNode.EVAL_GREATER ) )
                {
                    return true;
                }
            }
            else
            {
                if ( idx.hasValue( node.getValue(), id, SimpleNode.EVAL_LESSER ) )
                {
                    return true;
                }
            }
        }

        // resuscitate entry if need be
        if ( null == record.getEntry() )
        {
            record.setEntry( db.lookup( id ) );
        }

        // get the attribute associated with the node
        EntryAttribute attr = record.getEntry().get( 
                registries.getAttributeTypeRegistry().lookup( node.getAttribute() ) );

        // If we do not have the attribute just return false
        if ( null == attr )
        {
            return false;
        }

        /*
         * We need to iterate through all values and for each value we normalize
         * and use the comparator to determine if a match exists.
         */
        Normalizer normalizer = getNormalizer( attrId, ORDERING_MATCH );
        Comparator comparator = getComparator( attrId, ORDERING_MATCH );
        Object filterValue = node.getValue();

        /*
         * Cheaper to not check isGreater in one loop - better to separate
         * out into two loops which you choose to execute based on isGreater
         */
        if ( isGreaterOrLesser == SimpleNode.EVAL_GREATER )
        {
            for ( Value<?> value:attr )
            {
                Object normValue = normalizer.normalize( value.get() );

                // Found a value that is greater than or equal to the ava value
                if ( 0 >= comparator.compare( (String)((Value<?>)filterValue).get(), normValue ) )
                {
                    return true;
                }
            }
        }
        else
        {
            for ( Value<?> value:attr )
            {
                Object normValue = normalizer.normalize( value );

                // Found a value that is less than or equal to the ava value
                if ( 0 <= comparator.compare( filterValue, normValue ) )
                {
                    return true;
                }
            }
        }

        // no match so return false
        return false;
    }


    /**
     * Evaluates a simple presence attribute value assertion on a perspective
     * candidate.
     * 
     * @param attrId the name of the attribute tested for presence 
     * @param rec the IndexRecord of the perspective candidate
     * @return the ava evaluation on the perspective candidate
     * @throws NamingException if there is a database access failure
     */
    private boolean evalPresence( String attrId, IndexRecord rec ) throws NamingException
    {
        // First, check if the attributeType is indexed
        if ( db.hasUserIndexOn( attrId ) )
        {
            Index idx = db.getExistanceIndex();

            // We have a fast find if the entry contains 
            // this attribute type : as the AT was indexed, we
            // have a direct access to the entry.
            if ( idx.hasValue( attrId, rec.getEntryId() ) )
            {
                return true;
            }

            // Fallthrough : we may have some descendant 
            // attributes in some entries.
        }

        // get the attributes associated with the entry 
        ServerEntry entry = getEntry( rec );

        // Of course, if the entry does not contains any attributes
        // (very unlikely !!!), get out of here
        // TODO Can this simply happens ???
        if ( entry == null )
        {
            return false;
        }

        // Now, get the AttributeType associated with the Attribute id
        AttributeType type = registries.getAttributeTypeRegistry().lookup( 
                registries.getOidRegistry().getOid( attrId ) );

        // here, we may have some descendants if the attribute is not found
        if ( entry.get( type ) != null )
        {
            // The current entry contains this attribute. We can exit
            return true;
        }
        else
        {
            // The attribute was not found in the entry, but it may have
            // some descendant. Let's chack that
            if ( registries.getAttributeTypeRegistry().hasDescendants( attrId ) )
            {
                // Ok, we have to check for each descendant if pone of 
                // them is present into the entry
                Iterator<AttributeType> descendants = registries.getAttributeTypeRegistry().descendants( attrId );

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

                    if ( entry.get( descendant ) != null )
                    {
                        // We have found one descendant : exit
                        return true;
                    }
                }
            }

            // We have checked all the descendant, without success.
            // Get out, and return a failure status
            return false;
        }
    }


    /**
     * Evaluates a simple equality attribute value assertion on a perspective
     * candidate.
     *
     * @param node the equality node to evaluate
     * @param rec the IndexRecord of the perspective candidate
     * @return the ava evaluation on the perspective candidate
     * @throws NamingException if there is a database access failure
     */
    private boolean evalEquality( SimpleNode node, IndexRecord rec ) throws NamingException
    {
        String filterAttr = node.getAttribute();
        Value<?> filterValue = node.getValue();

        // First, check if the attributeType is indexed
        if ( db.hasUserIndexOn( filterAttr ) )
        {
            // Whatever the attribute has some descendants or not,
            // we will take a chance to get the associated entry
            // from the index.
            Index idx = db.getUserIndex( filterAttr );

            if ( idx.hasValue( filterValue, rec.getEntryId() ) )
            {
                return true;
            }
            else
            {
                // FallThrough : we may have some descendant attributes
                // which values are equal to the filter value.
            }
        }

        // Get the normalizer and comparator for this attributeType
        Normalizer normalizer = getNormalizer( filterAttr, EQUALITY_MATCH );
        Comparator<?> comparator = getComparator( filterAttr, EQUALITY_MATCH );

        /*
         * Get the attribute and if it is not set in rec then resusitate it
         * from the master table and set it in rec for use later if at all.
         * Before iterating through all values for a match check to see if the
         * AVA value is contained or the normalized form of the AVA value is 
         * contained.
         */
        // get the attributes associated with the entry 
        ServerEntry entry = getEntry( rec );

        // Of course, if the entry does not contains any attributes
        // (very unlikely !!!), get out of here
        // TODO Can this simply happens ???
        if ( entry == null )
        {
            return false;
        }

        // get the attribute associated with the node 
        AttributeType type = registries.getAttributeTypeRegistry().lookup( filterAttr );
        EntryAttribute attr = entry.get( type );

        if ( attr != null )
        {
            // We have found the attribute into the entry.
            // Check if the normalized value is present
            if ( attr.contains( filterValue ) )
            {
                // We are lucky.
                return true;
            }
            // Check if the unormalized value match
            else if ( matchValue( node, attr, type, normalizer, comparator ) )
            {
                return true;
            }
            else
            {
                // Fallthrough : we may have a descendant attribute containing the value
            }
        }
        else
        {
            // Fallthrough : we may have a descendant attribute containing the value
        }

        // If we do not have the attribute, loop through the descendant
        // May be the node Attribute has descendant ?
        if ( registries.getAttributeTypeRegistry().hasDescendants( filterAttr ) )
        {
            Iterator<AttributeType> descendants = registries.getAttributeTypeRegistry().descendants( filterAttr );

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

                attr = entry.get( descendant );

                if ( null == attr )
                {
                    continue;
                }
                else
                {
                    // check if the normalized value is present
                    if ( attr.contains( filterValue ) )
                    {
                        return true;
                    }
                    // Now check the unormalized value
                    else if ( matchValue( node, attr, type, normalizer, comparator ) )
                    {
                        return true;
                    }
                }
            }
        }

        return false;
    }


    /**
     * Gets the comparator for equality matching.
     *
     * @param attrId the attribute identifier
     * @return the comparator for equality matching
     * @throws NamingException if there is a failure
     */
    @SuppressWarnings("unchecked")
    private Comparator<?> getComparator( String attrId, int matchType ) throws NamingException
    {
        MatchingRule mrule = getMatchingRule( attrId, matchType );

        if ( mrule == null )
        {
            return ByteArrayComparator.INSTANCE;
        }

        return mrule.getComparator();
    }


    /**
     * Gets the normalizer for equality matching.
     *
     * @param attrId the attribute identifier
     * @return the normalizer for equality matching
     * @throws NamingException if there is a failure
     */
    private Normalizer getNormalizer( String attrId, int matchType ) throws NamingException
    {
        MatchingRule mrule = getMatchingRule( attrId, matchType );

        if ( mrule == null )
        {
            return NoOpNormalizer.INSTANCE;
        }

        return mrule.getNormalizer();
    }


    /**
     * Gets the matching rule for an attributeType.
     *
     * @param attrId the attribute identifier
     * @return the matching rule
     * @throws NamingException if there is a failure
     */
    private MatchingRule getMatchingRule( String attrId, int matchType ) throws NamingException
    {
        MatchingRule mrule = null;
        String oid = registries.getOidRegistry().getOid( attrId );
        AttributeType type = registries.getAttributeTypeRegistry().lookup( oid );

        switch ( matchType )
        {
            case ( EQUALITY_MATCH ):
                mrule = type.getEquality();
                break;

            case ( SUBSTRING_MATCH ):
                mrule = type.getSubstr();
                break;

            case ( ORDERING_MATCH ):
                mrule = type.getOrdering();
                break;

            default:
                throw new NamingException( "Unknown match type: " + matchType );
        }

        // if there is no ordering or substring matchingRule for the attributeType 
        // then we fallback to use the equality matching rule to determine the
        // normalizer and comparator to use.  This possible since 
        // comparators are redundant and enable ordering to occur.  So if
        // we can we will use the comparator of the ordering matchingRule
        // and if not we default to the equality matchingRule's comparator.
        if ( ( matchType != EQUALITY_MATCH ) && ( mrule == null ) )
        {
            return getMatchingRule( attrId, EQUALITY_MATCH );
        }

        return mrule;
    }
}
