/*
 * $Id: TestModuleConfig.java 471754 2006-11-06 14:55:09Z husted $
 *
 * 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.struts.config;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.digester3.Digester;
import org.xml.sax.SAXException;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Unit tests for the <code>org.apache.struts.config</code> package.
 *
 * @version $Rev: 471754 $ $Date: 2005-03-01 20:26:14 -0500 (Tue, 01 Mar 2005)
 *          $
 */
public class TestModuleConfig extends TestCase {

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

    /**
     * The ModuleConfig we are testing.
     */
    private ModuleConfig config = null;

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

    /**
     * Construct a new instance of this test case.
     *
     * @param name Name of the test case
     */
    public TestModuleConfig(final String name) {
        super(name);
    }

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

    /**
     * Set up instance variables required by this test case.
     */
    @Override
    public void setUp() {
        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();

        this.config = factoryObject.createModuleConfig("");
    }

    /**
     * Return the tests included in this test suite.
     * @return Test
     */
    public static Test suite() {
        return new TestSuite(TestModuleConfig.class);
    }

    /**
     * Tear down instance variables required by this test case.
     */
    @Override
    public void tearDown() {
        this.config = null;
    }

    // ------------------------------------------------ Individual Test Methods

    private void parseConfig(final String publicId, final String entityURL,
            final String strutsConfig) {
        // Prepare a Digester for parsing a struts-config.xml file
        Digester digester = new Digester();

        digester.push(this.config);
        digester.setNamespaceAware(true);
        digester.setValidating(true);
        digester.addRuleSet(new ConfigRuleSet());
        digester.register(publicId,
                TestModuleConfig.class.getResource(entityURL).toString());

        // Parse the test struts-config.xml file
        try (InputStream input =
                TestModuleConfig.class.getResourceAsStream(strutsConfig)) {

            assertNotNull("Got an input stream for " + strutsConfig, input);
            digester.parse(input);
            input.close();
        } catch (final IOException | SAXException e) {
            e.printStackTrace(System.out);
            fail("Parsing threw exception:  " + e);
        }
    }

    /**
     * Test parsing of a struts-config.xml file.
     */
    public void testParse() {
        testParseBase("-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",
            "/org/apache/struts/resources/struts-config_1_3.dtd",
            "/org/apache/struts/config/struts-config.xml");
    }

    /**
     * @param publicId String
     * @param entityURL String
     * @param strutsConfig String
     */
    public void testParseBase(final String publicId,
            final String entityURL, final String strutsConfig) {
        parseConfig(publicId, entityURL, strutsConfig);

        // Perform assertion tests on the parsed information
        FormBeanConfig[] fbcs = this.config.findFormBeanConfigs();

        assertNotNull("Found our form bean configurations", fbcs);
        assertEquals("Found three form bean configurations", 3, fbcs.length);

        ForwardConfig[] fcs = this.config.findForwardConfigs();

        assertNotNull("Found our forward configurations", fcs);
        assertEquals("Found three forward configurations", 3, fcs.length);

        ActionConfig logon = this.config.findActionConfig("/logon");

        assertNotNull("Found logon action configuration", logon);
        assertEquals("Found correct logon configuration", "logonForm",
            logon.getName());
    }

    /**
     * Tests a struts-config.xml that contains a custom mapping and property.
     */
    public void testCustomMappingParse() {
        // Prepare a Digester for parsing a struts-config.xml file
        testCustomMappingParseBase(
                "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",
                "/org/apache/struts/resources/struts-config_1_3.dtd",
                "/org/apache/struts/config/struts-config-custom-mapping.xml");
    }

    /** Tests a struts-config.xml that contains a custom mapping and property.
     * @param publicId String
     * @param entityURL String
     * @param strutsConfig String */
    private void testCustomMappingParseBase(final String publicId, final String entityURL,
            final String strutsConfig) {
        parseConfig(publicId, entityURL, strutsConfig);

        // Perform assertion tests on the parsed information
        ActionConfig map = this.config.findActionConfig("/editRegistration");

        assertNotNull("Cannot find editRegistration mapping", map);
        assertTrue(map instanceof CustomMappingTest);
        assertTrue("The custom mapping attribute has not been set",
            ((CustomMappingTest) map).getPublic());
    }

    /**
     * Test order of action mappings defined perserved.
     */
    public void testPreserveActionMappingsOrder() {
        parseConfig("-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",
            "/org/apache/struts/resources/struts-config_1_3.dtd",
            "/org/apache/struts/config/struts-config.xml");

        String[] paths =
            new String[] {
                "/editRegistration", "/editSubscription", "/logoff", "/logon",
                "/saveRegistration", "/saveSubscription", "/tour"
            };

        ActionConfig[] actions = this.config.findActionConfigs();

        for (int x = 0; x < paths.length; x++) {
            assertTrue("Action config out of order:" + actions[x].getPath(),
                paths[x].equals(actions[x].getPath()));
        }
    }
}
