/*
 * $Id: TestActionConfigMatcher.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 org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.junit.Assert;
import org.junit.Test;


/**
 * <p>Unit tests for <code>org.apache.struts.util.ActionConfigMatcher</code>.</p>
 *
 * @version $Rev: 471754 $ $Date: 2005-10-27 23:25:01 -0400 (Thu, 27 Oct 2005)
 *          $
 */
public class TestActionConfigMatcher {

    // ----------------------------------------------------------------- Basics

    // ------------------------------------------------------- Individual Tests

    // ---------------------------------------------------------- match()

    /**
     * testNoMatch
     */
    @Test
    public void testNoMatch() {
        ActionConfig[] configs = new ActionConfig[1];
        ActionConfig mapping = buildActionConfig("/foo");

        configs[0] = mapping;

        ActionConfigMatcher matcher = new ActionConfigMatcher(configs);

        Assert.assertNull("ActionConfig shouldn't be matched", matcher.match("/test"));
    }

    /**
     * testNoWildcardMatch
     */
    @Test
    public void testNoWildcardMatch() {
        ActionConfig[] configs = new ActionConfig[1];
        ActionConfig mapping = buildActionConfig("/fooBar");

        configs[0] = mapping;

        ActionConfigMatcher matcher = new ActionConfigMatcher(configs);

        Assert.assertNull("ActionConfig shouldn't be matched", matcher.match("/fooBar"));
    }

    /**
     * testShouldMatch
     */
    @Test
    public void testShouldMatch() {
        ActionConfig[] configs = new ActionConfig[1];
        ActionConfig mapping = buildActionConfig("/foo*");

        configs[0] = mapping;

        ActionConfigMatcher matcher = new ActionConfigMatcher(configs);

        ActionConfig matched = matcher.match("/fooBar");

        Assert.assertNotNull("ActionConfig should be matched", matched);
        Assert.assertEquals("ActionConfig should have two action forward",
            matched.findForwardConfigs().length, 2);
        Assert.assertEquals("ActionConfig should have two exception forward",
            matched.findExceptionConfigs().length, 2);
        Assert.assertEquals("ActionConfig should have properties",
            matched.getProperties().size(), 2);
    }

    /**
     * testCheckSubstitutionsMatch
     */
    @Test
    public void testCheckSubstitutionsMatch() {
        ActionConfig[] configs = new ActionConfig[1];
        ActionConfig mapping = buildActionConfig("/foo*");

        configs[0] = mapping;

        ActionConfigMatcher matcher = new ActionConfigMatcher(configs);
        ActionConfig m = matcher.match("/fooBar");

        Assert.assertEquals("Name hasn't been replaced", "name,Bar", m.getName());
        Assert.assertEquals("Path hasn't been replaced", "/fooBar", m.getPath());
        Assert.assertEquals("Scope isn't correct", "request", m.getScope());
        Assert.assertTrue("Unknown isn't correct", !m.getUnknown());
        Assert.assertTrue("Validate isn't correct", m.getValidate());

        Assert.assertEquals("Prefix hasn't been replaced", "foo,Bar", m.getPrefix());
        Assert.assertEquals("Suffix hasn't been replaced", "bar,Bar", m.getSuffix());
        Assert.assertEquals("Type hasn't been replaced", "foo.bar.BarAction", m.getType());
        Assert.assertEquals("Roles hasn't been replaced", "public,Bar", m.getRoles());
        Assert.assertEquals("Parameter hasn't been replaced", "param,Bar", m.getParameter());
        Assert.assertEquals("Attribute hasn't been replaced", "attrib,Bar", m.getAttribute());
        Assert.assertEquals("Forward hasn't been replaced", "fwd,Bar", m.getForward());
        Assert.assertEquals("Include hasn't been replaced", "include,Bar", m.getInclude());
        Assert.assertEquals("Input hasn't been replaced", "input,Bar", m.getInput());

        Assert.assertEquals("ActionConfig property not replaced",
            "testBar", m.getProperty("testprop2"));

        boolean found = false;
        for (ForwardConfig cfg : m.findForwardConfigs()) {
            if ("name".equals(cfg.getName())) {
                found = true;
                Assert.assertEquals("Path hasn't been replaced",
                    "path,Bar", cfg.getPath());
                Assert.assertEquals("Property foo hasn't been replaced",
                    "bar,Bar", cfg.getProperty("foo"));
                Assert.assertEquals("Module hasn't been replaced",
                    "modBar", cfg.getModule());
            }
        }

        Assert.assertTrue("The forward config 'name' cannot be found", found);
    }

    /**
     * testCheckMultipleSubstitutions
     */
    public void testCheckMultipleSubstitutions() {
        ActionMapping[] mapping = new ActionMapping[1];

        mapping[0] = new ActionMapping();
        mapping[0].setPath("/foo*");
        mapping[0].setName("name,{1}-{1}");

        ActionConfigMatcher matcher = new ActionConfigMatcher(mapping);
        ActionConfig m = matcher.match("/fooBar");

        Assert.assertEquals("Name hasn't been replaced correctly: " + m.getName(),
            "name,Bar-Bar", m.getName());
    }

    /**
     * build ActionConfig
     * @param path String
     * @return ActionConfig
     */
    private ActionConfig buildActionConfig(final String path) {
        ActionMapping mapping = new ActionMapping();

        mapping.setName("name,{1}");
        mapping.setPath(path);
        mapping.setScope("request");
        mapping.setUnknown(false);
        mapping.setValidate(true);

        mapping.setPrefix("foo,{1}");
        mapping.setSuffix("bar,{1}");

        mapping.setType("foo.bar.{1}Action");
        mapping.setRoles("public,{1}");
        mapping.setParameter("param,{1}");
        mapping.setAttribute("attrib,{1}");
        mapping.setForward("fwd,{1}");
        mapping.setInclude("include,{1}");
        mapping.setInput("input,{1}");

        setActionConfig(mapping);

        setExceptionConfig(mapping);


        mapping.freeze();

        return mapping;
    }

    /**
     * set ActionConfig
     * @param mapping ActionMapping
     */
    private void setActionConfig(final ActionMapping mapping) {
        ForwardConfig cfg = new ActionForward();

        cfg.setName("name");
        cfg.setPath("path,{1}");
        cfg.setModule("mod{1}");
        cfg.setProperty("foo", "bar,{1}");
        mapping.addForwardConfig(cfg);

        cfg = new ActionForward();
        cfg.setName("name2");
        cfg.setPath("path2");
        cfg.setModule("mod{1}");
        mapping.addForwardConfig(cfg);
    }

    /**
     * set ExceptionConfig
     * @param mapping ActionMapping
     */
    private void setExceptionConfig(final ActionMapping mapping) {
        ExceptionConfig excfg = new ExceptionConfig();

        excfg.setKey("foo");
        excfg.setType("foo.Bar");
        excfg.setPath("path");
        mapping.addExceptionConfig(excfg);

        excfg = new ExceptionConfig();
        excfg.setKey("foo2");
        excfg.setType("foo.Bar2");
        excfg.setPath("path2");
        mapping.addExceptionConfig(excfg);

        mapping.setProperty("testprop", "testval");
        mapping.setProperty("testprop2", "test{1}");
    }
}
