/*
 * 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.myfaces.test.config;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.myfaces.test.mock.MockRenderKit;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.faces.render.Renderer;
import java.io.IOException;
import java.net.URL;

/**
 * <p>Utility class to parse JavaServer Faces configuration resources, and
 * register JSF artifacts with the mock object hierarchy.</p>
 *
 * <p>The following artifacts are registered:</p>
 * <ul>
 *     <li><code>Converter</code> (by-id and by-class)</li>
 *     <li><code>RenderKit</code> and <code>Renderer</code></li>
 *     <li><code>UIComponent</code></li>
 *     <li><code>Validator</code></li>
 * </ul>
 *
 * <p>Note that any declared <em>factory</em> instances are explicitly
 * <strong>NOT</strong> registered, allowing the mock object hierarchy
 * of the Myfaces Test Framework to manage these APIs.</p>
 *
 * <p><strong>USAGE NOTE</strong> - If you are using an instance of this
 * class within a subclass of <code>AbstractJsfTestCase</code> or
 * <code>AbstractJmockJsfTestCase</code>, be sure you have completed the
 * <code>setUp()</code> processing in this base class before calling one
 * of the <code>parse()</code> methods.</p>
 *
 * @since 1.0.0
 */
public class ConfigParser
{

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

    /** Creates a new instance of ConfigParser */
    public ConfigParser()
    {
    }

    // ------------------------------------------------------ Manifest Constants

    /**
     * <p>Configuration resource URLs for the JSF RI.</p>
     */
    private static final String[] JSFRI_RESOURCES = { "/com/sun/faces/jsf-ri-runtime.xml", };

    /**
     * <p>Configuration resource URLs for Apache MyFaces.</p>
     */
    private static final String[] MYFACES_RESOURCES = { "/org/apache/myfaces/resource/standard-faces-config.xml", };

    /**
     * <p>Configuration resource URLs for Apache MyFaces 1.2.</p>
     */
    private static final String[] MYFACES_RESOURCES12 = { "/META-INF/standard-faces-config.xml", };

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

    /**
     * <p>The <code>Digester</code> instance we will use for parsing.</p>
     */
    private Digester digester = null;

    // ------------------------------------------------------- Public Properties

    /**
     * <p>Return the URLs of the platform configuration resources for this
     * application.  The following platforms are currently supported:</p>
     * <ul>
     * <li>JavaServer Faces Reference Implementation (version 1.0 - 1.2)</li>
     * <li>MyFaces (version 1.1)</li>
     * </ul>
     *
     * <p>If MyFaces (version 1.2), currently under development, does not change
     * the name of the configuration resource, it will be supported as well.</p>
     */
    public URL[] getPlatformURLs()
    {

        URL[] urls = translate(JSFRI_RESOURCES);
        if (urls[0] == null)
        {
            urls = translate(MYFACES_RESOURCES12);
            if (urls[0] == null)
            {
                urls = translate(MYFACES_RESOURCES);
            }
        }
        return urls;

    }

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

    /**
     * <p>Parse the specified JavaServer Faces configuration resource, causing
     * the appropriate JSF artifacts to be registered with the mock object
     * hierarchy.</p>
     *
     * @param url <code>URL</code> of the configuration resource to parse
     *
     * @exception IOException if an input/output error occurs
     * @exception SAXException if a parsing error occurs
     */
    public void parse(URL url) throws IOException, SAXException
    {

        // Acquire and configure the Digester instance we will use
        Digester digester = digester();
        ApplicationFactory factory = (ApplicationFactory) FactoryFinder
                .getFactory(FactoryFinder.APPLICATION_FACTORY);
        Application application = factory.getApplication();
        digester.push(application);

        // Perform the required parsing
        try
        {
            digester.parse(url);
        }
        finally
        {
            digester.clear();
        }

    }

    /**
     * <p>Parse the specified set of JavaServer Faces configuration resources,
     * in the listed order, causing the appropriate JSF artifacts to be registered
     * with the mock object hierarchy.</p>
     *
     * @param urls <code>URL</code>s of the configuration resources to parse
     *
     * @exception IOException if an input/output error occurs
     * @exception SAXException if a parsing error occurs
     */
    public void parse(URL[] urls) throws IOException, SAXException
    {

        for (int i = 0; i < urls.length; i++)
        {
            parse(urls[i]);
        }

    }

    // --------------------------------------------------------- Private Methods

    /**
     * <p>Return the <code>Digester</code> instance we will use for parsing,
     * creating and configuring a new instance if necessary.</p>
     */
    private Digester digester()
    {

        if (this.digester == null)
        {
            this.digester = new Digester();
            digester.addRule("faces-config/component", new ComponentRule());
            digester.addCallMethod("faces-config/component/component-type",
                    "setComponentType", 0);
            digester.addCallMethod("faces-config/component/component-class",
                    "setComponentClass", 0);
            digester.addRule("faces-config/converter", new ConverterRule());
            digester.addCallMethod("faces-config/converter/converter-id",
                    "setConverterId", 0);
            digester.addCallMethod("faces-config/converter/converter-class",
                    "setConverterClass", 0);
            digester.addCallMethod(
                    "faces-config/converter/converter-for-class",
                    "setConverterForClass", 0);
            digester.addRule("faces-config/render-kit", new RenderKitRule());
            digester.addRule("faces-config/render-kit/render-kit-id",
                    new RenderKitIdRule());
            digester.addRule("faces-config/render-kit/renderer",
                    new RendererRule());
            digester.addCallMethod(
                    "faces-config/render-kit/renderer/component-family",
                    "setComponentFamily", 0);
            digester.addCallMethod(
                    "faces-config/render-kit/renderer/renderer-class",
                    "setRendererClass", 0);
            digester.addCallMethod(
                    "faces-config/render-kit/renderer/renderer-type",
                    "setRendererType", 0);
            digester.addRule("faces-config/validator", new ValidatorRule());
            digester.addCallMethod("faces-config/validator/validator-id",
                    "setValidatorId", 0);
            digester.addCallMethod("faces-config/validator/validator-class",
                    "setValidatorClass", 0);
        }
        return this.digester;

    }

    /**
     * <p>Translate an array of resource names into an array of resource URLs.</p>
     *
     * @param names Resource names to translate
     */
    private URL[] translate(String[] names)
    {

        URL[] results = new URL[names.length];
        for (int i = 0; i < names.length; i++)
        {
            results[i] = this.getClass().getResource(names[i]);
        }
        return results;

    }

    // --------------------------------------------------------- Private Classes

    /**
     * <p>Data bean that stores information related to a component.</p>
     */
    class ComponentBean
    {

        private String componentClass;

        public String getComponentClass()
        {
            return this.componentClass;
        }

        public void setComponentClass(String componentClass)
        {
            this.componentClass = componentClass;
        }

        private String componentType;

        public String getComponentType()
        {
            return this.componentType;
        }

        public void setComponentType(String componentType)
        {
            this.componentType = componentType;
        }

    }

    /**
     * <p>Digester <code>Rule</code> for processing components.</p>
     */
    class ComponentRule extends Rule
    {

        public void begin(String namespace, String name, Attributes attributes)
        {
            getDigester().push(new ComponentBean());
        }

        public void end(String namespace, String name)
        {
            ComponentBean bean = (ComponentBean) getDigester().pop();
            Application application = (Application) getDigester().peek();
            application.addComponent(bean.getComponentType(), bean
                    .getComponentClass());
        }

    }

    /**
     * <p>Data bean that stores information related to a converter.</p>
     */
    class ConverterBean
    {

        private String converterClass;

        public String getConverterClass()
        {
            return this.converterClass;
        }

        public void setConverterClass(String converterClass)
        {
            this.converterClass = converterClass;
        }

        private String converterForClass;

        public String getConverterForClass()
        {
            return this.converterForClass;
        }

        public void setConverterForClass(String converterForClass)
        {
            this.converterForClass = converterForClass;
        }

        private String converterId;

        public String getConverterId()
        {
            return this.converterId;
        }

        public void setConverterId(String converterId)
        {
            this.converterId = converterId;
        }

    }

    /**
     * <p>Digester <code>Rule</code> for processing converers.</p>
     */
    class ConverterRule extends Rule
    {

        public void begin(String namespace, String name, Attributes attributes)
        {
            getDigester().push(new ConverterBean());
        }

        public void end(String namespace, String name)
        {
            ConverterBean bean = (ConverterBean) getDigester().pop();
            Application application = (Application) getDigester().peek();
            if (bean.getConverterId() != null)
            {
                application.addConverter(bean.getConverterId(), bean
                        .getConverterClass());
            }
            else
            {
                Class clazz = null;
                try
                {
                    clazz = classForName(bean.getConverterForClass());
                }
                catch (ClassNotFoundException e)
                {
                    throw new IllegalArgumentException(
                            "java.lang.ClassNotFoundException: "
                                    + bean.getConverterForClass());
                }
                application.addConverter(clazz, bean.getConverterClass());
            }
        }

    }

    private Class classForName(String type) throws ClassNotFoundException
    {
        try
        {
            // Try WebApp ClassLoader first
            return Class.forName(type, false, // do not initialize for faster startup
                    Thread.currentThread().getContextClassLoader());
        }
        catch (ClassNotFoundException ignore)
        {
            // fallback: Try ClassLoader for ClassUtils (i.e. the myfaces.jar lib)
            return Class.forName(type, false, // do not initialize for faster startup
                    this.getClass().getClassLoader());
        }
    }

    /**
     * <p>Digester <code>Rule</code> for processing render kits.</p>
     */
    class RenderKitRule extends Rule
    {

        public void begin(String namespace, String name, Attributes attributes)
        {
            RenderKitFactory factory = (RenderKitFactory) FactoryFinder
                    .getFactory(FactoryFinder.RENDER_KIT_FACTORY);
            getDigester().push(
                    factory.getRenderKit(null,
                            RenderKitFactory.HTML_BASIC_RENDER_KIT));
        }

        public void end(String namespace, String name)
        {
            getDigester().pop();
        }

    }

    /**
     * <p>Digester <code>Rule</code> for processing render kit identifiers.</p>
     */
    class RenderKitIdRule extends Rule
    {

        public void body(String namespace, String name, String text)
        {
            String renderKitId = text.trim();
            RenderKitFactory factory = (RenderKitFactory) FactoryFinder
                    .getFactory(FactoryFinder.RENDER_KIT_FACTORY);
            RenderKit renderKit = factory.getRenderKit(null, renderKitId);
            if (renderKit == null)
            {
                renderKit = new MockRenderKit();
                factory.addRenderKit(renderKitId, renderKit);
            }
            getDigester().pop();
            getDigester().push(renderKit);
        }

    }

    /**
     * <p>Data bean that stores information related to a renderer.</p>
     */
    class RendererBean
    {

        private String componentFamily;

        public String getComponentFamily()
        {
            return this.componentFamily;
        }

        public void setComponentFamily(String componentFamily)
        {
            this.componentFamily = componentFamily;
        }

        private String rendererClass;

        public String getRendererClass()
        {
            return this.rendererClass;
        }

        public void setRendererClass(String rendererClass)
        {
            this.rendererClass = rendererClass;
        }

        private String rendererType;

        public String getRendererType()
        {
            return this.rendererType;
        }

        public void setRendererType(String rendererType)
        {
            this.rendererType = rendererType;
        }

    }

    /**
     * <p>Digester <code>Rule</code> for processing renderers.</p>
     */
    class RendererRule extends Rule
    {

        public void begin(String namespace, String name, Attributes attributes)
        {
            getDigester().push(new RendererBean());
        }

        public void end(String namespace, String name)
        {
            RendererBean bean = (RendererBean) getDigester().pop();
            RenderKit kit = (RenderKit) getDigester().peek();
            Renderer renderer = null;
            Class clazz = null;
            try
            {
                clazz = classForName(bean.getRendererClass());
                renderer = (Renderer) clazz.newInstance();
            }
            catch (Exception e)
            {
                throw new IllegalArgumentException(
                        "Exception while trying to instantiate"
                                + " renderer class '" + bean.getRendererClass()
                                + "' : " + e.getMessage());
            }
            kit.addRenderer(bean.getComponentFamily(), bean.getRendererType(),
                    renderer);
        }

    }

    /**
     * <p>Data bean that stores information related to a validator.</p>
     */
    class ValidatorBean
    {

        private String validatorClass;

        public String getValidatorClass()
        {
            return this.validatorClass;
        }

        public void setValidatorClass(String validatorClass)
        {
            this.validatorClass = validatorClass;
        }

        private String validatorId;

        public String getValidatorId()
        {
            return this.validatorId;
        }

        public void setValidatorId(String validatorId)
        {
            this.validatorId = validatorId;
        }

    }

    /**
     * <p>Digester <code>Rule</code> for processing validators.</p>
     */
    class ValidatorRule extends Rule
    {

        public void begin(String namespace, String name, Attributes attributes)
        {
            getDigester().push(new ValidatorBean());
        }

        public void end(String namespace, String name)
        {
            ValidatorBean bean = (ValidatorBean) getDigester().pop();
            Application application = (Application) getDigester().peek();
            application.addValidator(bean.getValidatorId(), bean
                    .getValidatorClass());
        }

    }

}
