/*
 * Copyright (c) 1998, 2020 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.eis.EISDescriptor;
import org.eclipse.persistence.eis.EISLogin;
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();
            this.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)((EISLogin)project.getDatasourceLogin()).getProperty("directory");
            StringWriter stringWriter = new StringWriter();
            new XMLProjectWriter().write(project, stringWriter);
            log("DEPLOYMENT XML: " + stringWriter.toString());

            Project newProject = new XMLProjectReader().read(new StringReader(stringWriter.toString()));
            Map descriptors = project.getDescriptors();
            Iterator keysIterator = descriptors.keySet().iterator();
            while (keysIterator.hasNext()) {
                Class nextClass = (Class)keysIterator.next();
                EISDescriptor next = (EISDescriptor)descriptors.get(nextClass);
                for (int i = 0; i < next.getMappings().size(); i++) {
                    DatabaseMapping nextMapping = (DatabaseMapping)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());
            }

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

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

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

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

    public void tearDown() {
        try {
            connection.close();
            session.logout();
        } catch (Exception e) {
            this.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:");
        this.assertTrue(objects.size() > 0);
        if (objects.size() > 1) {
            log(objects.toString());
            this.assertTrue(((java.util.ArrayList)getControlObject()).size() == objects.size());
            this.assertEquals(getControlObject(), objects);
        } else if (objects.size() == 1) {
            log(objects.elementAt(0).toString());
            this.assertEquals(getControlObject(), objects.elementAt(0));
        }
    }

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

        session.login();
    }

    protected void updateProjectForWriting() throws Exception {
        if (session.isConnected()) {
            session.logout();
        }
        String directory = (String)((EISLogin)session.getDatasourceLogin()).getProperty("directory");
        ((EISLogin)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());
            this.assertTrue(((java.util.ArrayList)getControlObject()).size() == objects.size());
        } else {
            log(objects.elementAt(0).toString());
            this.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 = (Vector)session.readAllObjects(getSourceClass());
        this.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;
    }
}
