/*
 * Copyright (c) 1998, 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.oxm.mappings;

import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import jakarta.resource.ResourceException;
import jakarta.resource.cci.Connection;
import jakarta.resource.cci.RecordFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.eis.EISDescriptor;
import org.eclipse.persistence.eis.mappings.*;
import org.eclipse.persistence.internal.eis.adapters.xmlfile.XMLFileConnectionFactory;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.sessions.factories.XMLProjectReader;
import org.eclipse.persistence.sessions.factories.XMLProjectWriter;
import org.eclipse.persistence.testing.oxm.OXTestCase;
import org.w3c.dom.*;

public abstract class EISMappingTestCases extends OXTestCase {
    protected DatabaseSession session;
    protected Connection connection;
    protected XMLFileConnectionFactory connectionFactory;
    protected RecordFactory recordFactory;
    protected Class rootClass;
    protected Document controlDocument;
    private String resourceName;
    private DocumentBuilder parser;

    public EISMappingTestCases(String name) {
        super(name);
        setupParser();
        //doc pres is not supported with EIS
        if (platform == Platform.DOC_PRES) {
            platform = Platform.DOM;
        }
    }

    abstract protected String getTestDocument();

    abstract protected Object getControlObject();

    abstract protected java.util.ArrayList getRootClasses();

    abstract protected void createTables();

    protected void setupParser() {
        try {
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            builderFactory.setNamespaceAware(true);
            builderFactory.setIgnoringElementContentWhitespace(true);
            parser = builderFactory.newDocumentBuilder();
        } catch (Exception e) {
            e.printStackTrace();
            fail("An exception occurred during setup");
        }
    }

    protected void createRequiredTables() {
        try {
            createTables();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void setProject(Project project) {
        if (!(metadata == Metadata.JAVA)) {
            String directorySetting = (String) project.getDatasourceLogin().getProperty("directory");
            StringWriter stringWriter = new StringWriter();
            XMLProjectWriter.write(project, stringWriter);
            log("DEPLOYMENT XML: " + stringWriter.toString());

            Project newProject = XMLProjectReader.read(new StringReader(stringWriter.toString()));
            Map<Class<?>, ClassDescriptor> descriptors = project.getDescriptors();
            Iterator<Class<?>> keysIterator = descriptors.keySet().iterator();
            while (keysIterator.hasNext()) {
                Class<?> nextClass = keysIterator.next();
                EISDescriptor next = (EISDescriptor)descriptors.get(nextClass);
                for (int i = 0; i < next.getMappings().size(); i++) {
                    DatabaseMapping nextMapping = next.getMappings().get(i);
                    if (nextMapping instanceof EISOneToOneMapping) {
                        String attrName = nextMapping.getAttributeName();
                        Call oldMappingCall = ((EISOneToOneMapping)nextMapping).getSelectionQuery().getDatasourceCall();
                        if (oldMappingCall != null) {
                            ((EISOneToOneMapping)newProject.getDescriptor(nextClass).getMappingForAttributeName(attrName)).setSelectionCall(oldMappingCall);
                        }
                    } else if (nextMapping instanceof EISOneToManyMapping) {
                        String attrName = nextMapping.getAttributeName();
                        ((EISOneToManyMapping)newProject.getDescriptor(nextClass).getMappingForAttributeName(attrName)).setSelectionCall(((EISOneToManyMapping)nextMapping).getSelectionQuery().getDatasourceCall());
                    }
                }
                newProject.getDescriptor(nextClass).getQueryManager().setDeleteCall(next.getQueryManager().getDeleteCall());
                newProject.getDescriptor(nextClass).getQueryManager().setInsertCall(next.getQueryManager().getInsertCall());
                newProject.getDescriptor(nextClass).getQueryManager().setReadAllCall(next.getQueryManager().getReadAllCall());
                newProject.getDescriptor(nextClass).getQueryManager().setReadObjectCall(next.getQueryManager().getReadObjectCall());
                newProject.getDescriptor(nextClass).getQueryManager().setUpdateCall(next.getQueryManager().getUpdateCall());
            }

            newProject.getDatasourceLogin().setProperty("directory", directorySetting);
            session = newProject.createDatabaseSession();
        } else {
            session = project.createDatabaseSession();
        }
    }

    @Override
    public void setUp() {
        try {
            connection = connect();
            recordFactory = connectionFactory.getRecordFactory();
        } catch (Exception e) {
            e.printStackTrace();
            fail("An exception occurred during setup");
        }
    }

    public Connection connect() throws ResourceException {
        connectionFactory = new XMLFileConnectionFactory();
        connection = connectionFactory.getConnection();

        if (useLogging) {
            session.setLogLevel(SessionLog.FINEST);
        } else {
            session.setLogLevel(SessionLog.OFF);
        }
        return connection;
    }

    @Override
    public void tearDown() {
        try {
            connection.close();
            session.logout();
        } catch (Exception e) {
            fail("An exception occurred during teardown:");
            e.printStackTrace();
        }
    }

    public void testObjectToXMLDocument() throws Exception {
        updateProjectForWriting();

        createTables();

        Object objectToInsert = this.getControlObject();
        if (objectToInsert instanceof List) {
            int size = ((List)objectToInsert).size();
            for (int i = 0; i < size; i++) {
                session.insertObject(((List)objectToInsert).get(i));
            }
        } else {
            session.insertObject(this.getControlObject());
        }

        log("**testObjectToXMLDocument**");
        log("****Expected:");
        log(getControlDocument());
        log("\n****Actual:");
        Document testDocument = logTestDocument();

        assertXMLIdentical(getControlDocument(), testDocument);

    }

    public void testXMLDocumentToObject() throws Exception {
        updateProjectForReading();

        Vector objects = new Vector();
        for (int i = 0; i < getRootClasses().size(); i++) {
            objects.addAll(session.readAllObjects((Class)getRootClasses().get(i)));
        }

        log("**testXMLDocumentToObject**");
        log("****Expected:");
        log(getControlObject().toString());
        log("***Actual:");
        assertTrue(objects.size() > 0);
        if (objects.size() > 1) {
            log(objects.toString());
            assertTrue(((java.util.ArrayList)getControlObject()).size() == objects.size());
            assertEquals(getControlObject(), objects);
        } else if (objects.size() == 1) {
            log(objects.elementAt(0).toString());
            assertEquals(getControlObject(), objects.elementAt(0));
        }
    }

    protected void updateProjectForReading() throws Exception {
        if (session.isConnected()) {
            session.logout();
        }
        String directory = (String) session.getDatasourceLogin().getProperty("directory");
        session.getDatasourceLogin().setProperty("directory", directory + "/reading");

        session.login();
    }

    protected void updateProjectForWriting() throws Exception {
        if (session.isConnected()) {
            session.logout();
        }
        String directory = (String) session.getDatasourceLogin().getProperty("directory");
        session.getDatasourceLogin().setProperty("directory", directory + "/writing");

        session.login();
    }

    public void testObjectToXMLDocumentUOW() throws Exception {
        updateProjectForWriting();
        createTables();

        Object objectToInsert = this.getControlObject();
        if (objectToInsert instanceof List) {
            int size = ((List)objectToInsert).size();
            for (int i = 0; i < size; i++) {
                UnitOfWork uow = session.acquireUnitOfWork();
                uow.registerObject(((List)objectToInsert).get(i));
                uow.commit();
            }
        } else {
            UnitOfWork uow = session.acquireUnitOfWork();
            uow.registerObject(this.getControlObject());
            uow.commit();
        }

        log("**testObjectToXMLDocumentUOW**");
        log("****Expected:");
        log(getControlDocument());
        log("****Actual:");
        Document testDocument = logTestDocument();

        assertXMLIdentical(getControlDocument(), testDocument);
    }

    public void testXMLDocumentToObjectUOW() throws Exception {
        updateProjectForReading();
        session.getIdentityMapAccessor().initializeAllIdentityMaps();
        Vector objects = new Vector();
        for (int i = 0; i < getRootClasses().size(); i++) {
            UnitOfWork uow = session.acquireUnitOfWork();
            objects.addAll(uow.readAllObjects((Class)getRootClasses().get(i)));
        }

        log("**testXMLDocumentToObjectUOW**");
        log("****Expected:");
        log(getControlObject().toString());
        log("***Actual:");
        if (objects.size() > 1) {
            log(objects.toString());
            assertTrue(((java.util.ArrayList)getControlObject()).size() == objects.size());
        } else {
            log(objects.elementAt(0).toString());
            assertEquals(getControlObject(), objects.elementAt(0));
        }
    }

    public void testUOWDelete() throws Exception {
        updateProjectForWriting();

        createTables();
        //Insert some objects
        log("**testUOWDelete**");
        Object objectToInsert = this.getControlObject();
        if (objectToInsert instanceof List) {
            int size = ((List)objectToInsert).size();
            for (int i = 0; i < size; i++) {
                session.insertObject(((List)objectToInsert).get(i));
            }
        } else {
            session.insertObject(this.getControlObject());
        }

        log("****After inserts:");
        logTestDocument();

        UnitOfWork uow = session.acquireUnitOfWork();
        Object objectsRead = uow.readAllObjects(getSourceClass());

        if (objectsRead instanceof Vector) {
            uow.deleteAllObjects((Vector)objectsRead);
        } else {
            uow.deleteObject(objectsRead);
        }

        uow.commit();

        session.getIdentityMapAccessor().initializeAllIdentityMaps();
        Vector afterDeleteObjects = session.readAllObjects(getSourceClass());
        assertEquals("Objects were not all deleted", 0, afterDeleteObjects.size());

        log("****After commit deletes:");
        logTestDocument();
    }

    abstract protected Class getSourceClass();

    protected Document logTestDocument() throws Exception {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(getTestDocument());

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setIgnoringElementContentWhitespace(true);
        DocumentBuilder parser = builderFactory.newDocumentBuilder();
        Document returnDocument = parser.parse(inputStream);
        inputStream.close();
        log(returnDocument);
        removeEmptyTextNodes(returnDocument);

        return returnDocument;
    }

    protected void setControlDocument(String xmlResource) throws Exception {
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(xmlResource);
        resourceName = xmlResource;
        controlDocument = parser.parse(inputStream);
        removeEmptyTextNodes(controlDocument);
    }

    protected Document getControlDocument() {
        return controlDocument;
    }
}
