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 java.lang.System.arraycopy;
import static java.lang.String.format;
import static org.apache.commons.beanutils.ConstructorUtils.getAccessibleConstructor;
import static org.apache.commons.beanutils.ConvertUtils.convert;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * Rule implementation that creates a new object and pushes it onto the object stack. When the element is complete, the
 * object will be popped
 */
public class ObjectCreateRule
    extends Rule
{
    private static class DeferredConstructionCallback implements MethodInterceptor
    {
        Constructor<?> constructor;
        Object[] constructorArgs;
        ArrayList<RecordedInvocation> invocations = new ArrayList<RecordedInvocation>();
        Object delegate;

        DeferredConstructionCallback( Constructor<?> constructor, Object[] constructorArgs )
        {
            super();
            this.constructor = constructor;
            this.constructorArgs = constructorArgs;
        }

        public Object intercept( Object obj, Method method, Object[] args, MethodProxy proxy )
            throws Throwable
        {
            boolean hasDelegate;
            synchronized ( this ) {
                hasDelegate = delegate != null;
                if ( !hasDelegate )
                {
                    invocations.add( new RecordedInvocation( method, args ) );
                }
            }
            if ( hasDelegate ) {
                return proxy.invoke( delegate, args );
            }
            return proxy.invokeSuper( obj, args );
        }

        synchronized void establishDelegate()
            throws Exception
        {
            convertTo( constructor.getParameterTypes(), constructorArgs );
            delegate = constructor.newInstance( constructorArgs );
            for ( RecordedInvocation invocation : invocations )
            {
                invocation.getInvokedMethod().invoke( delegate, invocation.getArguments() );
            }
            constructor = null;
            constructorArgs = null;
            invocations = null;
        }
    }

    private static class ProxyManager
    {
        private final Class<?> clazz;
        private final Constructor<?> constructor;
        private final Object[] templateConstructorArguments;
        private final Digester digester;
        private final boolean hasDefaultConstructor;
        private Factory factory;

        ProxyManager( Class<?> clazz, Constructor<?> constructor, Object[] constructorArguments, Digester digester )
        {
            this.clazz = clazz;
            hasDefaultConstructor = getAccessibleConstructor(clazz, new Class[0]) != null;
            this.constructor = constructor;
            Class<?>[] argTypes = constructor.getParameterTypes();
            templateConstructorArguments = new Object[argTypes.length];
            if ( constructorArguments == null )
            {
                for ( int i = 0; i < templateConstructorArguments.length; i++ )
                {
                    if ( argTypes[i].equals(boolean.class) )
                    {
                        templateConstructorArguments[i] = Boolean.FALSE;
                        continue;
                    }
                    if ( argTypes[i].isPrimitive() )
                    {
                        templateConstructorArguments[i] = convert("0", argTypes[i]);
                        continue;
                    }
                    templateConstructorArguments[i] = null;
                }
            }
            else
            {
                if ( constructorArguments.length != argTypes.length )
                {
                    throw new IllegalArgumentException(
                        format( "wrong number of constructor arguments specified: %s instead of %s",
                        constructorArguments.length, argTypes.length ) );
                }
                arraycopy( constructorArguments, 0, templateConstructorArguments, 0, constructorArguments.length );
            }
            convertTo( argTypes, templateConstructorArguments );
            this.digester = digester;
        }

        Object createProxy()
        {
            Object[] constructorArguments = new Object[templateConstructorArguments.length];
            arraycopy( templateConstructorArguments, 0, constructorArguments, 0, constructorArguments.length );
            digester.pushParams( constructorArguments );

            DeferredConstructionCallback callback = new DeferredConstructionCallback(constructor, constructorArguments);

            Object result;
            if ( factory == null )
            {
                synchronized ( this )
                {
                    // check again for null now that we're in the synchronized block:
                    if ( factory == null )
                    {
                        Enhancer enhancer = new Enhancer();
                        enhancer.setSuperclass( clazz );
                        enhancer.setCallback( callback );
                        enhancer.setClassLoader( digester.getClassLoader() );
                        enhancer.setInterceptDuringConstruction(false);
                        if ( hasDefaultConstructor )
                        {
                            result = enhancer.create();
                        }
                        else
                        {
                            result = enhancer.create( constructor.getParameterTypes(), constructorArguments );
                        }
                        factory = (Factory) result;
                        return result;
                    }
                }
            }
            if ( hasDefaultConstructor )
            {
                result = factory.newInstance( callback );
            }
            else
            {
                result = factory.newInstance( constructor.getParameterTypes(),
                    constructorArguments, new Callback[] { callback } );
            }
            return result;
        }

        void finalize( Object proxy ) throws Exception
        {
            digester.popParams();
            ( ( DeferredConstructionCallback ) ( (Factory) proxy).getCallback( 0 ) ).establishDelegate();
        }
    }

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

    /**
     * Construct an object create rule with the specified class name.
     *
     * @param className Java class name of the object to be created
     */
    public ObjectCreateRule( String className )
    {
        this( className, (String) null );
    }

    /**
     * Construct an object create rule with the specified class.
     *
     * @param clazz Java class name of the object to be created
     */
    public ObjectCreateRule( Class<?> clazz )
    {
        this( clazz.getName(), (String) null );
        this.clazz = clazz;
    }

    /**
     * Construct an object create rule with the specified class name and an optional attribute name containing an
     * override.
     *
     * @param className Java class name of the object to be created
     * @param attributeName Attribute name which, if present, contains an override of the class name to create
     */
    public ObjectCreateRule( String className, String attributeName )
    {
        this.className = className;
        this.attributeName = attributeName;
    }

    /**
     * Construct an object create rule with the specified class and an optional attribute name containing an override.
     *
     * @param attributeName Attribute name which, if present, contains an
     * @param clazz Java class name of the object to be created override of the class name to create
     */
    public ObjectCreateRule( String attributeName, Class<?> clazz )
    {
        this( clazz.getName(), attributeName );
        this.clazz = clazz;
    }

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

    /**
     * The attribute containing an override class name if it is present.
     */
    protected String attributeName = null;

    /**
     * The Java class of the object to be created.
     */
    protected Class<?> clazz = null;

    /**
     * The Java class name of the object to be created.
     */
    protected String className = null;

    /**
     * The constructor argument types.
     *
     * @since 3.2
     */
    private Class<?>[] constructorArgumentTypes;

    /**
     * The explictly specified default constructor arguments which may be overridden by CallParamRules.
     *
     * @since 3.2
     */
    private Object[] defaultConstructorArguments;

    /**
     * Helper object for managing proxies.
     *
     * @since 3.2
     */
    private ProxyManager proxyManager;

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

    /**
     * Allows users to specify constructor argument types.
     *
     * @since 3.2
     */
    public void setConstructorArgumentTypes( Class<?>... constructorArgumentTypes )
    {
        if ( constructorArgumentTypes == null )
        {
            throw new IllegalArgumentException( "Parameter 'constructorArgumentTypes' must not be null" );
        }

        this.constructorArgumentTypes = constructorArgumentTypes;
    }

    /**
     * Allows users to specify default constructor arguments.  If a default/no-arg constructor is not available
     * for the target class, these arguments will be used to create the proxy object.  For any argument
     * not supplied by a {@link CallParamRule}, the corresponding item from this array will be used
     * to construct the final object as well.
     *
     * @since 3.2
     */
    public void setDefaultConstructorArguments( Object... constructorArguments )
    {
        if ( constructorArguments == null )
        {
            throw new IllegalArgumentException( "Parameter 'constructorArguments' must not be null" );
        }

        this.defaultConstructorArguments = constructorArguments;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void begin( String namespace, String name, Attributes attributes )
        throws Exception
    {
        Class<?> clazz = this.clazz;

        if ( clazz == null )
        {
            // Identify the name of the class to instantiate
            String realClassName = className;
            if ( attributeName != null )
            {
                String value = attributes.getValue( attributeName );
                if ( value != null )
                {
                    realClassName = value;
                }
            }
            if ( getDigester().getLogger().isDebugEnabled() )
            {
                getDigester().getLogger().debug( format( "[ObjectCreateRule]{%s} New '%s'",
                                                         getDigester().getMatch(),
                                                         realClassName ) );
            }

            // Instantiate the new object and push it on the context stack
            clazz = getDigester().getClassLoader().loadClass( realClassName );
        }
        Object instance;
        if ( constructorArgumentTypes == null || constructorArgumentTypes.length == 0 )
        {
            if ( getDigester().getLogger().isDebugEnabled() )
            {
                getDigester().getLogger().debug( format( "[ObjectCreateRule]{%s} New '%s' using default empty constructor",
                                                         getDigester().getMatch(),
                                                         clazz.getName() ) );
            }

            instance = clazz.newInstance();
        }
        else
        {
            if ( proxyManager == null )
            {
                synchronized ( this )
                {
                    if ( proxyManager == null )
                    {
                        Constructor<?> constructor = getAccessibleConstructor( clazz, constructorArgumentTypes );

                        if ( constructor == null )
                        {
                            throw new SAXException( format( "[ObjectCreateRule]{%s} Class '%s' does not have a construcor with types %s",
                                                            getDigester().getMatch(),
                                                            clazz.getName(),
                                                            Arrays.toString( constructorArgumentTypes ) ) );
                        }
                        proxyManager = new ProxyManager(clazz, constructor, defaultConstructorArguments, getDigester());
                    }
                }
            }
            instance = proxyManager.createProxy();
        }
        getDigester().push( instance );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void end( String namespace, String name )
        throws Exception
    {
        Object top = getDigester().pop();

        if ( proxyManager != null )
        {
            proxyManager.finalize(top);
        }

        if ( getDigester().getLogger().isDebugEnabled() )
        {
            getDigester().getLogger().debug( format( "[ObjectCreateRule]{%s} Pop '%s'",
                                                     getDigester().getMatch(),
                                                     top.getClass().getName() ) );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        return format( "ObjectCreateRule[className=%s, attributeName=%s]", className, attributeName );
    }

    private static void convertTo( Class<?>[] types, Object[] array )
    {
        if ( array.length != types.length )
        {
            throw new IllegalArgumentException();
        }
        // this piece of code is adapted from CallMethodRule
        for ( int i = 0; i < array.length; i++ )
        {
            // convert nulls and convert stringy parameters for non-stringy param types
            if ( array[i] == null
                    || ( array[i] instanceof String && !String.class.isAssignableFrom( types[i] ) ) )
            {
                array[i] = convert( (String) array[i], types[i] );
            }
        }
    }

}
