package org.apache.torque.generator.source;

/*
 * 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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

import java.util.ArrayList;
import java.util.List;

import org.apache.torque.generator.GeneratorException;
import org.junit.Before;
import org.junit.Test;

public class SourcePathTest
{
    private SourceElement root;
    private SourceElement firstLevel1;
    private SourceElement firstLevel2;
    private SourceElement firstLevel3;
    private SourceElement secondLevel;
    private SourceElement thirdLevel;

    @Before
    public void setUp()
    {
        root = new SourceElement("root");
        firstLevel1 = new SourceElement("firstLevel1");
        root.getChildren().add(firstLevel1);
        firstLevel2  = new SourceElement("firstLevel2");
        root.getChildren().add(firstLevel2);
        firstLevel3 = new SourceElement("firstLevel3");
        root.getChildren().add(firstLevel3);
        secondLevel = new SourceElement("secondLevel");
        firstLevel2.getChildren().add(secondLevel);
        thirdLevel = new SourceElement("thirdLevel");
        secondLevel.getChildren().add(thirdLevel);
    }

    @Test
    public void testGetPath() throws GeneratorException
    {
        assertEquals(
                "root/firstLevel2/secondLevel/thirdLevel",
                SourcePath.getPathAsString(thirdLevel));
    }

    @Test(expected = GeneratorException.class)
    public void testGetPathInfiniteLoop() throws GeneratorException
    {
        SourceElement loopElement1 = new SourceElement("loopElement1");
        SourceElement loopElement2 = new SourceElement("loopElement2");
        loopElement1.getChildren().add(loopElement2);
        loopElement2.getChildren().add(loopElement1);
        SourcePath.getPathAsString(loopElement1);
    }

    @Test
    public void testGetElementFromRootWithSlash()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "/");
        List<SourceElement> expected = new ArrayList<SourceElement>();
        expected.add(root);
        assertEquals(expected, result);
    }

    @Test
    public void testGetElementFromRootSingleRelativeElement()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "root");
        List<SourceElement> expected = new ArrayList<SourceElement>();
        expected.add(root);
        assertEquals(expected, result);
    }

    @Test
    public void testGetElementFromRootSingleRelativeElementNoMatch()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "root1");
        assertEquals(0, result.size());
    }

    @Test
    public void testGetElementFromRootSingleAbsoluteElement()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "/root");
        List<SourceElement> expected = new ArrayList<SourceElement>();
        expected.add(root);
        assertEquals(expected, result);
    }

    @Test
    public void testGetElementFromRootSingleAbsoluteElementNoMatch()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "/root1");
        assertEquals(0, result.size());
    }

    @Test
    public void testGetElementFromRootWildcardAtStart()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "/*");
        List<SourceElement> expected = new ArrayList<SourceElement>();
        expected.add(root);
        assertEquals(expected, result);
    }

    @Test
    public void testGetElementFromRootWildcardInMiddle()
    {
        List<SourceElement> result
                = SourcePath.getElementsFromRoot(root, "/root/*/secondLevel");
        List<SourceElement> expected = new ArrayList<SourceElement>();
        expected.add(secondLevel);
        assertEquals(expected, result);
    }

// does not yet work
//    @Test
//    public void testGetElementFromRootBacktoRootWithParent()
//    {
//        List<SourceElement> result
//                = SourcePath.getElementsFromRoot(root, "/root/../root");
//        List<SourceElement> expected = new ArrayList<SourceElement>();
//        expected.add(root);
//        assertEquals(expected, result);
//    }

    @Test
    public void testGetElementFromRootParentInMiddle()
    {
        List<SourceElement> result = SourcePath.getElementsFromRoot(
                root,
                "/root/firstLevel1/../firstLevel2");
        List<SourceElement> expected = new ArrayList<SourceElement>();
        expected.add(firstLevel2);
        assertEquals(expected, result);
    }

    @Test
    public void testGetPreceding()
    {
        List<SourceElement> result
                = SourcePath.getPreceding(firstLevel2, "firstLevel1");
        assertEquals(1, result.size());
        assertSame(firstLevel1, result.get(0));
    }

    @Test
    public void testGetPrecedingNoMatch()
    {
        List<SourceElement> result
                = SourcePath.getPreceding(firstLevel2, "firstLevel2");
        assertEquals(0, result.size());
    }
    @Test

    public void testGetFollowing()
    {
        List<SourceElement> result
                = SourcePath.getFollowing(firstLevel2, "firstLevel3");
        assertEquals(1, result.size());
        assertSame(firstLevel3, result.get(0));
    }

    @Test
    public void testGetFollowingNoMatch()
    {
        List<SourceElement> result
                = SourcePath.getFollowing(firstLevel2, "firstLevel2");
        assertEquals(0, result.size());
    }
}
