/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation.  All rights 
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer. 
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:  
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must 
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written 
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache 
*    XMLBeans", nor may "Apache" appear in their name, without prior 
*    written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2000-2003 BEA Systems 
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/

package drtcases;

import org.openuri.nameworld.NameworldDocument;
import org.openuri.nameworld.NameworldDocument.Nameworld;
import org.openuri.nameworld.Loc;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlObject;

import java.io.File;

import javax.xml.namespace.QName;

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

public class NameworldTest extends TestCase
{
    public NameworldTest(String name) { super(name); }
    public static Test suite() { return new TestSuite(NameworldTest.class); }

    public static void testWorld1() throws Exception
    {
        NameworldDocument doc = (NameworldDocument)
                    XmlObject.Factory.parse(TestEnv.xbeanCase("nameworld/world1.xml"));

        Assert.assertEquals(new QName("http://openuri.org/nameworld", "nameworld"), doc.schemaType().getDocumentElementName());

        QName[] contents = new QName[]
        {
            new QName("http://bar.com/", "barcity"),
            new QName("http://foo.com/", "footown"),
            new QName("http://bar.com/", "barvillage"),
            new QName("http://bar.com/", "bartown"),
            new QName("http://foo.com/", "foovillage"),
            new QName("http://bar.com/", "barvillage"),
            new QName("http://foo.com/", "foocity"),
            new QName("http://bar.com/", "bartown"),
            new QName("http://foo.com/", "foovillage"),
            new QName("http://foo.com/", "footown"),
            new QName("http://bar.com/", "barvillage"),
            new QName("http://foo.com/", "foovillage"),
        };
        int t = 0;

        Nameworld world = doc.getNameworld();
        Nameworld.Island[] islands = world.getIslandArray();
        for (int i = 0; i < islands.length; i++)
        {
            Loc[] locs = islands[i].getLocationArray();
            for (int j = 0; j < locs.length; j++)
            {
                Loc.Reference[] refs = locs[j].getReferenceArray();
                for (int k = 0; k < refs.length; k++)
                {
                    Assert.assertEquals(contents[t++], refs[k].getTo());
                }
            }
        }
    }

    /*
    public static void testAccessByName() throws Exception
    {
        NameworldDocument doc = (NameworldDocument)
                    XmlLoader.Factory.parse(TestEnv.xbeanCase("nameworld/world1.xml"),
                    NameworldDocument.type);
        String[] contents = new String[]
        {
            "http://foo.com/",
            "foocity",
            "footown",
            "foovillage",
            "http://bar.com/",
            "barcity",
            "bartown",
            "barvillage",
        };
        int t = 0;
        Nameworld world = (Nameworld)doc.elementByName(new Name("http://openuri.org/nameworld", "nameworld"), 0);
        for (int i = 0; i < world.countOfElementByName(new Name("http://openuri.org/nameworld", "island")); i++)
        {
            Nameworld.Island island = (Nameworld.Island)world.elementByName(new Name("http://openuri.org/nameworld", "island"), i);
            Assert.assertEquals(contents[t++], ((SimpleValue)island.attributeByName(new Name("targetNamespace"))).stringValue());
            for (int j = 0; j < island.countOfElementByName(new Name( "http://openuri.org/nameworld", "location")); j++)
            {
                Loc loc = (Loc)island.elementByName(new Name("http://openuri.org/nameworld", "location"), j);
                Assert.assertEquals(contents[t++], ((SimpleValue)loc.attributeByName(new Name("name"))).stringValue());
            }
        }
    }
    */

}
