package org.apache.commons.digester3;

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.xml.sax.Attributes;

/**
 * <p>
 * Default implementation of the <code>Rules</code> interface that supports the standard rule matching behavior. This
 * class can also be used as a base class for specialized <code>Rules</code> implementations.
 * </p>
 * <p>
 * The matching policies implemented by this class support two different types of pattern matching rules:
 * </p>
 * <ul>
 * <li><em>Exact Match</em> - A pattern "a/b/c" exactly matches a <code>&lt;c&gt;</code> element, nested inside a
 * <code>&lt;b&gt;</code> element, which is nested inside an <code>&lt;a&gt;</code> element.</li>
 * <li><em>Tail Match</em> - A pattern "&#42;/a/b" matches a <code>&lt;b&gt;</code> element, nested inside an
 * <code>&lt;a&gt;</code> element, no matter how deeply the pair is nested.</li>
 * </ul>
 * <p>
 * Note that wildcard patterns are ignored if an explicit match can be found (and when multiple wildcard patterns match,
 * only the longest, ie most explicit, pattern is considered a match).
 * </p>
 * <p>
 * See the package documentation for package org.apache.commons.digester3 for more information.
 * </p>
 */

public class RulesBase
    extends AbstractRulesImpl
{

    // ----------------------------------------------------- Instance Variables

    /**
     * The set of registered Rule instances, keyed by the matching pattern. Each value is a List containing the Rules
     * for that pattern, in the order that they were orginally registered.
     */
    protected HashMap<String, List<Rule>> cache = new HashMap<String, List<Rule>>();

    /**
     * The subset of registered Rule instances with wildcard pattern.
     */
    protected List<String> wildcardCache = new LinkedList<String>();

    /**
     * The set of registered Rule instances, in the order that they were originally registered.
     */
    protected ArrayList<Rule> rules = new ArrayList<Rule>();

    // ------------------------------------------------------------- Properties

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDigester( final Digester digester )
    {
        super.setDigester( digester );
        for ( final Rule rule : rules )
        {
            rule.setDigester( digester );
        }
    }

    // --------------------------------------------------------- Public Methods

    /**
     * {@inheritDoc}
     */
    @Override
    protected void registerRule( String pattern, final Rule rule )
    {
        // to help users who accidently add '/' to the end of their patterns
        final int patternLength = pattern.length();
        if ( patternLength > 1 && pattern.endsWith( "/" ) )
        {
            pattern = pattern.substring( 0, patternLength - 1 );
        }

        List<Rule> list = cache.get( pattern );
        if ( list == null )
        {
            list = new ArrayList<Rule>();
            if ( pattern.startsWith( "*/" ) )
            {
                wildcardCache.add( pattern.substring( 1 ) );
            }
            cache.put( pattern, list );
        }
        list.add( rule );
        rules.add( rule );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void clear()
    {
        wildcardCache.clear();
        cache.clear();
        rules.clear();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Rule> match( final String namespaceURI, final String pattern, final String name, final Attributes attributes )
    {
        // List rulesList = (List) this.cache.get(pattern);
        List<Rule> rulesList = lookup( namespaceURI, pattern );
        if ( ( rulesList == null ) || ( rulesList.size() < 1 ) )
        {
            // Find the longest key, ie more discriminant
            String longKey = "";
            for ( final String key : wildcardCache )
            {
                if ( ( pattern.equals( key.substring( 1 ) ) || pattern.endsWith( key ) )
                    && key.length() > longKey.length() )
                {
                    longKey = key;
                }
            }
            if ( !longKey.isEmpty() )
            {
                rulesList = lookup( namespaceURI, "*" + longKey );
            }
        }
        if ( rulesList == null )
        {
            rulesList = new ArrayList<Rule>();
        }
        return ( rulesList );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Rule> rules()
    {
        return ( this.rules );
    }

    // ------------------------------------------------------ Protected Methods

    /**
     * Return a List of Rule instances for the specified pattern that also match the specified namespace URI (if any).
     * If there are no such rules, return <code>null</code>.
     *
     * @param namespaceURI Namespace URI to match, or <code>null</code> to select matching rules regardless of namespace
     *            URI
     * @param pattern Pattern to be matched
     * @return a List of Rule instances for the specified pattern that also match the specified namespace URI (if any)
     */
    protected List<Rule> lookup( final String namespaceURI, final String pattern )
    {
        // Optimize when no namespace URI is specified
        final List<Rule> list = this.cache.get( pattern );
        if ( list == null )
        {
            return ( null );
        }
        if ( ( namespaceURI == null ) || ( namespaceURI.isEmpty() ) )
        {
            return ( list );
        }

        // Select only Rules that match on the specified namespace URI
        final ArrayList<Rule> results = new ArrayList<Rule>();
        for ( final Rule item : list )
        {
            if ( ( namespaceURI.equals( item.getNamespaceURI() ) ) || ( item.getNamespaceURI() == null ) )
            {
                results.add( item );
            }
        }
        return ( results );
    }

}
