/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     rbarkhouse - 2.2 - initial implementation
package org.eclipse.persistence.testing.jaxb.dynamic;

import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
import org.eclipse.persistence.testing.jaxb.dynamic.util.MyList;
import org.w3c.dom.Document;

import junit.framework.TestCase;

public class DynamicJAXBCollectionTestCases extends TestCase {

    public DynamicJAXBCollectionTestCases(String name) throws Exception {
        super(name);
    }

    @Override
    public String getName() {
        return "Dynamic JAXB: Collections: " + super.getName();
    }

    public void testXSDSingleListUnmarshal() throws Exception {
        InputStream schemaStream = ClassLoader.getSystemResourceAsStream(XSD_SINGLE);
        jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(schemaStream, null, null, null);

        InputStream xmlStream = ClassLoader.getSystemResourceAsStream(XSD_SINGLE_INSTANCE);
        JAXBElement<DynamicEntity> jaxbElement = (JAXBElement<DynamicEntity>) jaxbContext.createUnmarshaller().unmarshal(xmlStream);

        DynamicEntity customer = jaxbElement.getValue();
        assertNotNull("Could not create Dynamic Entity.", customer);

        List<DynamicEntity> phoneNumbers = customer.<List<DynamicEntity>>get("phoneNumbers");
        assertEquals("Unexpected number of phoneNumbers returned.", 3, phoneNumbers.size());
        DynamicEntity firstPhoneNumber = phoneNumbers.get(0);
        assertEquals("Incorrect phoneNumber type.", "work", firstPhoneNumber.get("type"));
    }

    public void testXSDMultipleListUnmarshal() throws Exception {
        InputStream schemaStream = ClassLoader.getSystemResourceAsStream(XSD_MULTI);
        jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(schemaStream, null, null, null);

        InputStream xmlStream = ClassLoader.getSystemResourceAsStream(XSD_MULTI_INSTANCE);
        JAXBElement<DynamicEntity> jaxbElement = (JAXBElement<DynamicEntity>) jaxbContext.createUnmarshaller().unmarshal(xmlStream);

        DynamicEntity customer = jaxbElement.getValue();
        assertNotNull("Could not create Dynamic Entity.", customer);

        List<DynamicEntity> addresses = customer.<List<DynamicEntity>>get("addresses");
        assertEquals("Unexpected number of addresses returned.", 2, addresses.size());
        DynamicEntity firstAddress = addresses.get(0);
        assertEquals("Incorrect address city.", "Any Town", firstAddress.get("city"));

        List<DynamicEntity> phoneNumbers = customer.<List<DynamicEntity>>get("phoneNumbers");
        assertEquals("Unexpected number of phoneNumbers returned.", 3, phoneNumbers.size());
        DynamicEntity firstPhoneNumber = phoneNumbers.get(0);
        assertEquals("Incorrect phoneNumber type.", "work", firstPhoneNumber.get("type"));

        List<DynamicEntity> addresses2 = customer.<List<DynamicEntity>>get("addresses2");
        assertEquals("Unexpected number of addresses returned.", 1, addresses2.size());
        DynamicEntity firstAddress2 = addresses2.get(0);
        assertEquals("Incorrect address city.", "Big City", firstAddress2.get("city"));
    }

    public void testOXMSingleListVector() throws Exception {
        InputStream iStream = classLoader.getResourceAsStream(OXM_SINGLE_VECTOR);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + OXM_SINGLE_VECTOR + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(PACKAGE, new StreamSource(iStream));

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone1.set("type", "HOME"); phone1.set("number", "1234567890");

        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone2.set("type", "WORK"); phone2.set("number", "1235678904");

        Vector<DynamicEntity> phones = new Vector<DynamicEntity>(3);
        phones.add(phone1); phones.add(phone2);

        person.set("phones", phones);

        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        Vector<DynamicEntity> readPhones = readPerson.get("phones");
        assertEquals("Unexpected number of phoneNumbers returned.", 2, readPhones.size());
        DynamicEntity firstPhoneNumber = readPhones.get(0);
        assertEquals("Incorrect phoneNumber type.", "HOME", firstPhoneNumber.get("type"));
    }

    public void testOXMSingleListSet() throws Exception {
        InputStream iStream = classLoader.getResourceAsStream(OXM_SINGLE_SET);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + OXM_SINGLE_SET + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(PACKAGE, new StreamSource(iStream));

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone1.set("type", "HOME"); phone1.set("number", "1234567890");

        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone2.set("type", "WORK"); phone2.set("number", "1235678904");

        HashSet<DynamicEntity> phones = new HashSet<DynamicEntity>(3);
        phones.add(phone1); phones.add(phone2);

        person.set("phones", phones);

        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        Set<DynamicEntity> readPhones = readPerson.get("phones");
        assertEquals("Unexpected number of phoneNumbers returned.", 2, readPhones.size());
    }

    public void testOXMSingleListList() throws Exception {
        InputStream iStream = classLoader.getResourceAsStream(OXM_SINGLE_LIST);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + OXM_SINGLE_LIST + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(PACKAGE, new StreamSource(iStream));

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone1.set("type", "HOME"); phone1.set("number", "1234567890");

        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone2.set("type", "WORK"); phone2.set("number", "1235678904");

        LinkedList<DynamicEntity> phones = new LinkedList<DynamicEntity>();
        phones.add(phone1); phones.add(phone2);

        person.set("phones", phones);

        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        LinkedList<DynamicEntity> readPhones = readPerson.get("phones");
        assertEquals("Unexpected number of phoneNumbers returned.", 2, readPhones.size());
        DynamicEntity firstPhoneNumber = readPhones.get(0);
        assertEquals("Incorrect phoneNumber type.", "HOME", firstPhoneNumber.get("type"));
    }

    public void testOXMSingleListCustom() throws Exception {
        InputStream iStream = classLoader.getResourceAsStream(OXM_SINGLE_CUSTOM);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + OXM_SINGLE_CUSTOM + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(PACKAGE, new StreamSource(iStream));

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone1.set("type", "HOME"); phone1.set("number", "1234567890");

        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone2.set("type", "WORK"); phone2.set("number", "1235678904");

        MyList phones = new MyList();
        phones.add(phone1); phones.add(phone2);

        person.set("phones", phones);

        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        MyList readPhones = readPerson.get("phones");
        assertEquals("Unexpected number of phoneNumbers returned.", 2, readPhones.size());
        DynamicEntity firstPhoneNumber = (DynamicEntity) readPhones.get(0);
        assertEquals("Incorrect phoneNumber type.", "HOME", firstPhoneNumber.get("type"));
    }

    /*
    public void testOXMSingleListMap() throws Exception {
        InputStream iStream = classLoader.getResourceAsStream(OXM_SINGLE_MAP);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + OXM_SINGLE_MAP + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        metadataSourceMap.put(PACKAGE, new StreamSource(iStream));

        Map<String, Map<String, Source>> properties = new HashMap<String, Map<String, Source>>();
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataSourceMap);

        JaxbClassLoader jcl = new JaxbClassLoader(classLoader);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(jcl, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone1.set("type", "HOME"); phone1.set("number", "1234567890");

        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone2.set("type", "WORK"); phone2.set("number", "1235678904");

        HashMap<String, DynamicEntity> phones = new HashMap<String, DynamicEntity>();
        phones.put("phone1", phone1); phones.put("phone2", phone2);

        person.set("phones", phones);

        print(person);

        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        MyList readPhones = readPerson.get("phones");
        assertEquals("Unexpected number of phoneNumbers returned.", 2, readPhones.size());
        DynamicEntity firstPhoneNumber = (DynamicEntity) readPhones.get(0);
        assertEquals("Incorrect phoneNumber type.", "HOME", firstPhoneNumber.get("type"));
    }
    */

    // Utility methods
    // ====================================================================

    private void print(Object o) throws Exception {
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(o, System.err);
    }

    private static String XSD_SINGLE = "org/eclipse/persistence/testing/jaxb/dynamic/SingleList.xsd";
    private static String XSD_SINGLE_INSTANCE = "org/eclipse/persistence/testing/jaxb/dynamic/SingleList.xml";
    private static String XSD_MULTI = "org/eclipse/persistence/testing/jaxb/dynamic/MultipleList.xsd";
    private static String XSD_MULTI_INSTANCE = "org/eclipse/persistence/testing/jaxb/dynamic/MultipleList.xml";

    private static String OXM_SINGLE_VECTOR = "org/eclipse/persistence/testing/jaxb/dynamic/singlelistvector-oxm.xml";
    private static String OXM_SINGLE_SET = "org/eclipse/persistence/testing/jaxb/dynamic/singlelistset-oxm.xml";
    private static String OXM_SINGLE_LIST = "org/eclipse/persistence/testing/jaxb/dynamic/singlelistlist-oxm.xml";
    private static String OXM_SINGLE_CUSTOM = "org/eclipse/persistence/testing/jaxb/dynamic/singlelistcustom-oxm.xml";
    private static String OXM_SINGLE_MAP = "org/eclipse/persistence/testing/jaxb/dynamic/singlelistmap-oxm.xml";

    private static final String PACKAGE = "mynamespace";
    private static final String PERSON = "Person";
    private static final String PHONE = "Phone";


    private DynamicJAXBContext jaxbContext;

    private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

}
