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 static org.apache.commons.beanutils.BeanUtils.setProperty;
import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptor;

import static java.lang.String.format;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.logging.Log;
import org.xml.sax.Attributes;

/**
 * <p>
 * Rule implementation that sets properties on the object at the top of the stack, based on child elements with names
 * matching properties on that object.
 * </p>
 * <p>
 * Example input that can be processed by this rule:
 * </p>
 * 
 * <pre>
 *   [widget]
 *    [height]7[/height]
 *    [width]8[/width]
 *    [label]Hello, world[/label]
 *   [/widget]
 * </pre>
 * <p>
 * For each child element of [widget], a corresponding setter method is located on the object on the top of the digester
 * stack, the body text of the child element is converted to the type specified for the (sole) parameter to the setter
 * method, then the setter method is invoked.
 * </p>
 * <p>
 * This rule supports custom mapping of xml element names to property names. The default mapping for particular elements
 * can be overridden by using {@link #SetNestedPropertiesRule(String[] elementNames, String[] propertyNames)}. This
 * allows child elements to be mapped to properties with different names. Certain elements can also be marked to be
 * ignored.
 * </p>
 * <p>
 * A very similar effect can be achieved using a combination of the <code>BeanPropertySetterRule</code> and the
 * <code>ExtendedBaseRules</code> rules manager; this <code>Rule</code>, however, works fine with the default
 * <code>RulesBase</code> rules manager.
 * </p>
 * <p>
 * Note that this rule is designed to be used to set only "primitive" bean properties, eg String, int, boolean. If some
 * of the child xml elements match ObjectCreateRule rules (ie cause objects to be created) then you must use one of the
 * more complex constructors to this rule to explicitly skip processing of that xml element, and define a SetNextRule
 * (or equivalent) to handle assigning the child object to the appropriate property instead.
 * </p>
 * <p>
 * <b>Implementation Notes</b>
 * </p>
 * <p>
 * This class works by creating its own simple Rules implementation. When begin is invoked on this rule, the digester's
 * current rules object is replaced by a custom one. When end is invoked for this rule, the original rules object is
 * restored. The digester rules objects therefore behave in a stack-like manner.
 * </p>
 * <p>
 * For each child element encountered, the custom Rules implementation ensures that a special AnyChildRule instance is
 * included in the matches returned to the digester, and it is this rule instance that is responsible for setting the
 * appropriate property on the target object (if such a property exists). The effect is therefore like a
 * "trailing wildcard pattern". The custom Rules implementation also returns the matches provided by the underlying
 * Rules implementation for the same pattern, so other rules are not "disabled" during processing of a
 * SetNestedPropertiesRule.
 * </p>
 * <p>
 * TODO: Optimise this class. Currently, each time begin is called, new AnyChildRules and AnyChildRule objects are
 * created. It should be possible to cache these in normal use (though watch out for when a rule instance is invoked
 * re-entrantly!).
 * </p>
 * 
 * @since 1.6
 */
public class SetNestedPropertiesRule
    extends Rule
{

    private Log log = null;

    private boolean trimData = true;

    private boolean allowUnknownChildElements = false;

    private final HashMap<String, String> elementNames = new HashMap<String, String>();

    // ----------------------------------------------------------- Constructors

    /**
     * Base constructor, which maps every child element into a bean property with the same name as the xml element.
     * <p>
     * It is an error if a child xml element exists but the target java bean has no such property (unless
     * {@link #setAllowUnknownChildElements(boolean)} has been set to true).
     * </p>
     */
    public SetNestedPropertiesRule()
    {
        // nothing to set up
    }

    /**
     * <p>
     * Convenience constructor which overrides the default mappings for just one property.
     * </p>
     * <p>
     * For details about how this works, see
     * {@link #SetNestedPropertiesRule(String[] elementNames, String[] propertyNames)}.
     * </p>
     * 
     * @param elementName is the child xml element to match
     * @param propertyName is the java bean property to be assigned the value of the specified xml element. This may be
     *            null, in which case the specified xml element will be ignored.
     */
    public SetNestedPropertiesRule( String elementName, String propertyName )
    {
        elementNames.put( elementName, propertyName );
    }

    /**
     * <p>
     * Constructor which allows element->property mapping to be overridden.
     * </p>
     * <p>
     * Two arrays are passed in. One contains xml element names and the other java bean property names. The element name
     * / property name pairs are matched by position; in order words, the first string in the element name array
     * corresponds to the first string in the property name array and so on.
     * </p>
     * <p>
     * If a property name is null or the xml element name has no matching property name due to the arrays being of
     * different lengths then this indicates that the xml element should be ignored.
     * </p>
     * <h5>Example One</h5>
     * <p>
     * The following constructs a rule that maps the <code>alt-city</code> element to the <code>city</code> property and
     * the <code>alt-state</code> to the <code>state</code> property. All other child elements are mapped as usual using
     * exact name matching. <code><pre>
     *      SetNestedPropertiesRule(
     *                new String[] {"alt-city", "alt-state"}, 
     *                new String[] {"city", "state"});
     * </pre></code>
     * </p>
     * <h5>Example Two</h5>
     * <p>
     * The following constructs a rule that maps the <code>class</code> xml element to the <code>className</code>
     * property. The xml element <code>ignore-me</code> is not mapped, ie is ignored. All other elements are mapped as
     * usual using exact name matching. <code><pre>
     *      SetPropertiesRule(
     *                new String[] {"class", "ignore-me"}, 
     *                new String[] {"className"});
     * </pre></code>
     * </p>
     * 
     * @param elementNames names of elements to map
     * @param propertyNames names of properties mapped to
     */
    public SetNestedPropertiesRule( String[] elementNames, String[] propertyNames )
    {
        for ( int i = 0, size = elementNames.length; i < size; i++ )
        {
            String propName = null;
            if ( i < propertyNames.length )
            {
                propName = propertyNames[i];
            }

            this.elementNames.put( elementNames[i], propName );
        }
    }

    /**
     * Constructor which allows element->property mapping to be overridden.
     *
     * @param elementNames names of elements->properties to map
     * @since 3.0
     */
    public SetNestedPropertiesRule( Map<String, String> elementNames )
    {
        if ( elementNames != null && !elementNames.isEmpty() )
        {
            this.elementNames.putAll( elementNames );
        }
    }

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

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDigester( Digester digester )
    {
        super.setDigester( digester );
        log = digester.getLogger();
    }

    /**
     * When set to true, any text within child elements will have leading and trailing whitespace removed before
     * assignment to the target object. The default value for this attribute is true.
     *
     * @param trimData flag to have leading and trailing whitespace removed
     */
    public void setTrimData( boolean trimData )
    {
        this.trimData = trimData;
    }

    /**
     * Return the flag to have leading and trailing whitespace removed.
     *
     * @see #setTrimData(boolean)
     * @return flag to have leading and trailing whitespace removed
     */
    public boolean getTrimData()
    {
        return trimData;
    }

    /**
     * Determines whether an error is reported when a nested element is encountered for which there is no corresponding
     * property-setter method.
     * <p>
     * When set to false, any child element for which there is no corresponding object property will cause an error to
     * be reported.
     * <p>
     * When set to true, any child element for which there is no corresponding object property will simply be ignored.
     * <p>
     * The default value of this attribute is false (unknown child elements are not allowed).
     *
     * @param allowUnknownChildElements flag to ignore any child element for which there is no corresponding
     *        object property
     */
    public void setAllowUnknownChildElements( boolean allowUnknownChildElements )
    {
        this.allowUnknownChildElements = allowUnknownChildElements;
    }

    /**
     * Return the flag to ignore any child element for which there is no corresponding object property
     *
     * @return flag to ignore any child element for which there is no corresponding object property
     * @see #setAllowUnknownChildElements(boolean)
     */
    public boolean getAllowUnknownChildElements()
    {
        return allowUnknownChildElements;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void begin( String namespace, String name, Attributes attributes )
        throws Exception
    {
        Rules oldRules = getDigester().getRules();
        AnyChildRule anyChildRule = new AnyChildRule();
        anyChildRule.setDigester( getDigester() );
        AnyChildRules newRules = new AnyChildRules( anyChildRule );
        newRules.init( getDigester().getMatch() + "/", oldRules );
        getDigester().setRules( newRules );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void body( String namespace, String name, String text )
        throws Exception
    {
        AnyChildRules newRules = (AnyChildRules) getDigester().getRules();
        getDigester().setRules( newRules.getOldRules() );
    }

    /**
     * Add an additional custom xml-element -> property mapping.
     * <p>
     * This is primarily intended to be used from the xml rules module (as it is not possible there to pass the
     * necessary parameters to the constructor for this class). However it is valid to use this method directly if
     * desired.
     *
     * @param elementName the xml-element has to be mapped
     * @param propertyName the property name target
     */
    public void addAlias( String elementName, String propertyName )
    {
        elementNames.put( elementName, propertyName );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        return format( "SetNestedPropertiesRule[allowUnknownChildElements=%s, trimData=%s, elementNames=%s]",
                       allowUnknownChildElements,
                       trimData,
                       elementNames );
    }

    // ----------------------------------------- local classes

    /** Private Rules implementation */
    private class AnyChildRules
        implements Rules
    {
        private String matchPrefix = null;

        private Rules decoratedRules = null;

        private final ArrayList<Rule> rules = new ArrayList<Rule>( 1 );

        private final AnyChildRule rule;

        public AnyChildRules( AnyChildRule rule )
        {
            this.rule = rule;
            rules.add( rule );
        }

        public Digester getDigester()
        {
            return null;
        }

        public void setDigester( Digester digester )
        {
        }

        public String getNamespaceURI()
        {
            return null;
        }

        public void setNamespaceURI( String namespaceURI )
        {
        }

        public void add( String pattern, Rule rule )
        {
        }

        public void clear()
        {
        }

        public List<Rule> match( String namespaceURI, String matchPath, String name, Attributes attributes )
        {
            List<Rule> match = decoratedRules.match( namespaceURI, matchPath, name, attributes );

            if ( ( matchPath.startsWith( matchPrefix ) ) && ( matchPath.indexOf( '/', matchPrefix.length() ) == -1 ) )
            {

                // The current element is a direct child of the element
                // specified in the init method, so we want to ensure that
                // the rule passed to this object's constructor is included
                // in the returned list of matching rules.

                if ( ( match == null || match.size() == 0 ) )
                {
                    // The "real" rules class doesn't have any matches for
                    // the specified path, so we return a list containing
                    // just one rule: the one passed to this object's
                    // constructor.
                    return rules;
                }
                // The "real" rules class has rules that match the current
                // node, so we return this list *plus* the rule passed to
                // this object's constructor.
                //
                // It might not be safe to modify the returned list,
                // so clone it first.
                LinkedList<Rule> newMatch = new LinkedList<Rule>( match );
                newMatch.addLast( rule );
                return newMatch;
            }
            return match;
        }

        public List<Rule> rules()
        {
            // This is not actually expected to be called during normal
            // processing.
            //
            // There is only one known case where this is called; when a rule
            // returned from AnyChildRules.match is invoked and throws a
            // SAXException then method Digester.endDocument will be called
            // without having "uninstalled" the AnyChildRules ionstance. That
            // method attempts to invoke the "finish" method for every Rule
            // instance - and thus needs to call rules() on its Rules object,
            // which is this one. Actually, java 1.5 and 1.6beta2 have a
            // bug in their xml implementation such that endDocument is not
            // called after a SAXException, but other parsers (eg Aelfred)
            // do call endDocument. Here, we therefore need to return the
            // rules registered with the underlying Rules object.
            log.debug( "AnyChildRules.rules invoked." );
            return decoratedRules.rules();
        }

        public void init( String prefix, Rules rules )
        {
            matchPrefix = prefix;
            decoratedRules = rules;
        }

        public Rules getOldRules()
        {
            return decoratedRules;
        }
    }

    private class AnyChildRule
        extends Rule
    {

        private String currChildElementName = null;

        @Override
        public void begin( String namespaceURI, String name, Attributes attributes )
            throws Exception
        {
            currChildElementName = name;
        }

        @Override
        public void body( String namespace, String name, String text )
            throws Exception
        {
            String propName = currChildElementName;
            if ( elementNames.containsKey( currChildElementName ) )
            {
                // overide propName
                propName = elementNames.get( currChildElementName );
                if ( propName == null )
                {
                    // user wants us to ignore this element
                    return;
                }
            }

            boolean debug = log.isDebugEnabled();

            if ( debug )
            {
                log.debug( "[SetNestedPropertiesRule]{" + getDigester().getMatch() + "} Setting property '" + propName
                    + "' to '" + text + "'" );
            }

            // Populate the corresponding properties of the top object
            Object top = getDigester().peek();
            if ( debug )
            {
                if ( top != null )
                {
                    log.debug( "[SetNestedPropertiesRule]{" + getDigester().getMatch() + "} Set "
                        + top.getClass().getName() + " properties" );
                }
                else
                {
                    log.debug( "[SetPropertiesRule]{" + getDigester().getMatch() + "} Set NULL properties" );
                }
            }

            if ( trimData )
            {
                text = text.trim();
            }

            if ( !allowUnknownChildElements )
            {
                // Force an exception if the property does not exist
                // (BeanUtils.setProperty() silently returns in this case)
                if ( top instanceof DynaBean )
                {
                    DynaProperty desc = ( (DynaBean) top ).getDynaClass().getDynaProperty( propName );
                    if ( desc == null )
                    {
                        throw new NoSuchMethodException( "Bean has no property named " + propName );
                    }
                }
                else
                /* this is a standard JavaBean */
                {
                    PropertyDescriptor desc = getPropertyDescriptor( top, propName );
                    if ( desc == null )
                    {
                        throw new NoSuchMethodException( "Bean has no property named " + propName );
                    }
                }
            }

            try
            {
                setProperty( top, propName, text );
            }
            catch ( NullPointerException e )
            {
                log.error( "NullPointerException: " + "top=" + top + ",propName=" + propName + ",value=" + text + "!" );
                throw e;
            }
        }

        @Override
        public void end( String namespace, String name )
            throws Exception
        {
            currChildElementName = null;
        }
    }

}
