package org.apache.velocity;

/*
 * 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.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.List;

import org.apache.velocity.context.Context;
import org.apache.velocity.context.InternalContextAdapterImpl;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.directive.Scope;
import org.apache.velocity.runtime.directive.StopCommand;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.ResourceManager;

/**
 * This class is used for controlling all template
 * operations. This class uses a parser created
 * by JavaCC to create an AST that is subsequently
 * traversed by a Visitor.
 *
 * <pre>
 * // set up and initialize Velocity before this code block
 *
 * Template template = Velocity.getTemplate("test.wm");
 * Context context = new VelocityContext();
 *
 * context.put("foo", "bar");
 * context.put("customer", new Customer());
 *
 * template.merge(context, writer);
 * </pre>
 *
 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
 * @version $Id$
 */
public class Template extends Resource
{
    /*
     * The name of the variable to use when placing
     * the scope object into the context.
     */
    private String scopeName = "template";
    private boolean provideScope = false;

    private VelocityException errorCondition = null;

    /** Default constructor */
    public Template()
    {
        super();
        
        setType(ResourceManager.RESOURCE_TEMPLATE);
    }

    /**
     *  gets the named resource as a stream, parses and inits
     *
     * @return true if successful
     * @throws ResourceNotFoundException if template not found
     *          from any available source.
     * @throws ParseErrorException if template cannot be parsed due
     *          to syntax (or other) error.
     * @throws IOException problem reading input stream
     */
    public boolean process()
        throws ResourceNotFoundException, ParseErrorException
    {
        data = null;
        InputStream is = null;
        errorCondition = null;

        /*
         *  first, try to get the stream from the loader
         */
        try
        {
            is = resourceLoader.getResourceStream(name);
        }
        catch( ResourceNotFoundException rnfe )
        {
            /*
             *  remember and re-throw
             */

            errorCondition = rnfe;
            throw rnfe;
        }

        /*
         *  if that worked, lets protect in case a loader impl
         *  forgets to throw a proper exception
         */

        if (is != null)
        {
            /*
             *  now parse the template
             */

            try
            {
                BufferedReader br = new BufferedReader( new InputStreamReader( is, encoding ) );
                data = rsvc.parse( br, name);
                initDocument();
                return true;
            }
            catch( UnsupportedEncodingException  uce )
            {
                String msg = "Template.process : Unsupported input encoding : " + encoding
                + " for template " + name;

                errorCondition  = new ParseErrorException( msg );
                throw errorCondition;
            }
            catch ( ParseException pex )
            {
                /*
                 *  remember the error and convert
                 */
                errorCondition =  new ParseErrorException(pex, name);
                throw errorCondition;
            }
            catch ( TemplateInitException pex )
            {
                errorCondition = new ParseErrorException( pex, name);
                throw errorCondition;
            }
            /**
             * pass through runtime exceptions
             */
            catch( RuntimeException e )
            {
                errorCondition = new VelocityException("Exception thrown processing Template "
                    +getName(), e);
                throw errorCondition;
            }
            finally
            {
                /*
                 *  Make sure to close the inputstream when we are done.
                 */
                try
                {
                    is.close();
                }
                catch(IOException e)
                {
                    // If we are already throwing an exception then we want the original
                    // exception to be continued to be thrown, otherwise, throw a new Exception.
                    if (errorCondition == null)
                    {
                         throw new VelocityException(e);
                    }                    
                }
            }
        }
        else
        {
            /*
             *  is == null, therefore we have some kind of file issue
             */
            errorCondition = new ResourceNotFoundException("Unknown resource error for resource " + name );
            throw errorCondition;
        }
    }

    /**
     *  initializes the document.  init() is not longer
     *  dependant upon context, but we need to let the
     *  init() carry the template name down throught for VM
     *  namespace features
     * @throws TemplateInitException When a problem occurs during the document initialization.
     */
    public void initDocument()
    throws TemplateInitException
    {
        /*
         *  send an empty InternalContextAdapter down into the AST to initialize it
         */

        InternalContextAdapterImpl ica = new InternalContextAdapterImpl(  new VelocityContext() );

        try
        {
            /*
             *  put the current template name on the stack
             */

            ica.pushCurrentTemplateName( name );
            ica.setCurrentResource( this );

            /*
             *  init the AST
             */

            ((SimpleNode)data).init( ica, rsvc);

            String property = scopeName+'.'+RuntimeConstants.PROVIDE_SCOPE_CONTROL;
            provideScope = rsvc.getBoolean(property, provideScope);
        }
        finally
        {
            /*
             *  in case something blows up...
             *  pull it off for completeness
             */

            ica.popCurrentTemplateName();
            ica.setCurrentResource( null );
        }

    }

    /**
     * The AST node structure is merged with the
     * context to produce the final output.
     *
     *  @param context Conext with data elements accessed by template
     *  @param writer output writer for rendered template
     *  @throws ResourceNotFoundException if template not found
     *          from any available source.
     *  @throws ParseErrorException if template cannot be parsed due
     *          to syntax (or other) error.
     *  @throws MethodInvocationException When a method on a referenced object in the context could not invoked.
     */
    public void merge( Context context, Writer writer)
        throws ResourceNotFoundException, ParseErrorException, MethodInvocationException
    {
        merge(context, writer, null);
    }

    
    /**
     * The AST node structure is merged with the
     * context to produce the final output.
     *
     *  @param context Conext with data elements accessed by template
     *  @param writer output writer for rendered template
     *  @param macroLibraries a list of template files containing macros to be used when merging
     *  @throws ResourceNotFoundException if template not found
     *          from any available source.
     *  @throws ParseErrorException if template cannot be parsed due
     *          to syntax (or other) error.
     *  @throws MethodInvocationException When a method on a referenced object in the context could not invoked.
     *  @since 1.6
     */
    public void merge( Context context, Writer writer, List macroLibraries)
        throws ResourceNotFoundException, ParseErrorException, MethodInvocationException
    {
        /*
         *  we shouldn't have to do this, as if there is an error condition,
         *  the application code should never get a reference to the
         *  Template
         */

        if (errorCondition != null)
        {
            throw errorCondition;
        }

        if( data != null)
        {
            /*
             *  create an InternalContextAdapter to carry the user Context down
             *  into the rendering engine.  Set the template name and render()
             */

            InternalContextAdapterImpl ica = new InternalContextAdapterImpl( context );

            /**
             * Set the macro libraries
             */
            ica.setMacroLibraries(macroLibraries);

            if (macroLibraries != null)
            {
                for (int i = 0; i < macroLibraries.size(); i++)
                {
                    /**
                     * Build the macro library
                     */
                    try
                    {
                        rsvc.getTemplate((String) macroLibraries.get(i));
                    }
                    catch (ResourceNotFoundException re)
                    {
                        /*
                        * the macro lib wasn't found.  Note it and throw
                        */
                        rsvc.getLog().error("template.merge(): " +
                                "cannot find template " +
                                (String) macroLibraries.get(i));
                        throw re;
                    }
                    catch (ParseErrorException pe)
                    {
                        /*
                        * the macro lib was found, but didn't parse - syntax error
                        *  note it and throw
                        */
                        rsvc.getLog().error("template.merge(): " +
                                "syntax error in template " +
                                (String) macroLibraries.get(i) + ".");
                        throw pe;
                    }
                    
                    catch (Exception e)
                    {
                        throw new RuntimeException("Template.merge(): parse failed in template  " +
                                (String) macroLibraries.get(i) + ".", e);
                    }
                }
            }

            if (provideScope)
            {
                ica.put(scopeName, new Scope(this, ica.get(scopeName)));
            }
            try
            {
                ica.pushCurrentTemplateName( name );
                ica.setCurrentResource( this );

                ( (SimpleNode) data ).render( ica, writer);
            }
            catch (StopCommand stop)
            {
                if (!stop.isFor(this))
                {
                    throw stop;
                }
                else if (rsvc.getLog().isDebugEnabled())
                {
                    rsvc.getLog().debug(stop.getMessage());
                }
            }
            catch (IOException e)
            {
                throw new VelocityException("IO Error rendering template '"+ name + "'", e);
            }
            finally
            {
                /*
                 *  lets make sure that we always clean up the context
                 */
                ica.popCurrentTemplateName();
                ica.setCurrentResource( null );

                if (provideScope)
                {
                    Object obj = ica.get(scopeName);
                    if (obj instanceof Scope)
                    {
                        Scope scope = (Scope)obj;
                        if (scope.getParent() != null)
                        {
                            ica.put(scopeName, scope.getParent());
                        }
                        else if (scope.getReplaced() != null)
                        {
                            ica.put(scopeName, scope.getReplaced());
                        }
                        else
                        {
                            ica.remove(scopeName);
                        }
                    }
                }
            }
        }
        else
        {
            /*
             * this shouldn't happen either, but just in case.
             */

            String msg = "Template.merge() failure. The document is null, " +
                "most likely due to parsing error.";

            throw new RuntimeException(msg);

        }
    }
}
