/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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 dom.detailed;

import common.Common;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import xbean.dom.id.FooDocument;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

public class IDTest {
    private String P = File.separator;

    // Test the getElementById() DOM API with DTDs , run with jvm arg -Dcases.location
    @Test
    void testGetElemById() throws Exception {
        Document doc;
        Element element;
        String tagname;
        XmlOptions xmlOptions = new XmlOptions();
        xmlOptions.setLoadUseDefaultResolver();
        XmlObject o = XmlObject.Factory.parse(new File(Common.CASEROOT + P + "xbean" + P + "dom" + P + "id.xml"));
        doc = (Document) o.getDomNode();
        element = doc.getElementById("CANADA");
        assertNotNull(element);

        tagname = element.getTagName();
        assertEquals("emp:address", tagname, "throw_Equals");
        assertNull(doc.getDoctype());
    }

    // test getElementById() with schema containing DTD with ID definition for untyped XmlObject
    @Test
    void testIDSchema() throws Exception {
        String dtdAndData =
            "<!DOCTYPE xs:schema PUBLIC \"-//W3C//DTD XMLSCHEMA 200102//EN\" \"XMLSchema.dtd\" [\n" +
            "<!ELEMENT first_name (#PCDATA)>\n" +
            "<!ELEMENT hobby (#PCDATA)>\n" +
            "<!ELEMENT homepage EMPTY>\n" +
            "<!ATTLIST homepage href CDATA #REQUIRED>\n" +
            "<!ELEMENT last_name (#PCDATA)>\n" +
            "<!ELEMENT middle_initial (#PCDATA)>\n" +
            "<!ELEMENT name (first_name, middle_initial?, last_name)>\n" +
            "<!ELEMENT person (name, profession+, homepage?, hobby?)>\n" +
            "<!ATTLIST person\n" +
            "        born CDATA #REQUIRED\n" +
            "        died CDATA #REQUIRED\n" +
            "        id ID #REQUIRED\n" +
            ">\n" +
            "<!ELEMENT profession (#PCDATA)>\n" +
            "]>" +
            "<person id=\"25\" born=\"yday\" />";

        XmlObject o = XmlObject.Factory.parse(dtdAndData);
        Document n = (Document) o.getDomNode();
        Element elem = n.getElementById("25");
        assertNotNull(elem);
        System.out.println("Elem: " + elem.getNodeName());

        Element elemInvalid = n.getElementById("100");
        assertNull(elemInvalid);
    }

    // typed XmlObject
    @Test
    @Disabled("doesn't work anymore - xerces 2.11 is not calling the DeclHandler and so no ID attribute is added")
    public void testSchemaWithDTD() throws Exception {
        XmlOptions opt = new XmlOptions();
        List err = new ArrayList();
        opt.setErrorListener(err);
        // opt.setLoadSaxSchema(true);

        String instance =
            "<foo xmlns='http://xbean/dom/id'>" +
            "    <person id=\"abc\"><firstname>John</firstname></person>" +
            "</foo>";

        try {
            FooDocument fooDoc = FooDocument.Factory.parse(instance, opt);

            Document d = (Document) fooDoc.getDomNode();
            Element elem = d.getElementById("abc");
            assertNotNull(elem);

            Element elemInvalid = d.getElementById("100");
            assertNull(elemInvalid);
        } catch (XmlException xme) {
            Collection xmlerrs = xme.getErrors();
            for (Object xmlerr : xmlerrs) {
                XmlError xerr = (XmlError) xmlerr;
                System.out.println("Exception:" + xerr.getMessage());
            }
            throw (new XmlException(new Throwable("XmlException occured")));
        }

        // parse errors
        for (Object o : err) {
            System.out.println("Err:" + o);
        }
    }

}
