/*
 * 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.tests.unitofwork;

import java.util.Vector;

import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.models.employee.domain.Employee;
import org.eclipse.persistence.testing.models.employee.domain.PhoneNumber;


/**
 * Test that exceptions are thrown when attempts to conform query results in a unit of work fail.
 * References: CR 2188.
 *
 * Description:
 * The test generally involves two classes, the second having a
 * pointer to the first.  In this case PhoneNumber has an Employee
 * owner, and Contact has a MailAddress instance.
 * In a Unit of Work, an object of the first class is modified, or has
 * one of its field's changed.  Then a query is executed on the second
 * class (i.e PhoneNumber), which is conditional on the fields of its
 * instance of the first class.
 * The changes and queries are coordinated so that the former should alter
 * the outcome of the latter.
 * If Toplink is unable to conform the results of the query with the
 * original change, a warning exception should be thrown.
 */
public class UnitOfWorkConformExceptionTest extends org.eclipse.persistence.testing.framework.AutoVerifyTestCase {
    protected Employee bob;
    protected UnitOfWork uow;
    boolean pass;
    ReadObjectQuery phoneNumberQuery;
    ReadAllQuery phoneNumbersQuery;
    ReadAllQuery contactsQuery;

    public UnitOfWorkConformExceptionTest() {
        setDescription("Test that exceptions are thrown when attempts to conform query results in a unit of work fail.");
    }

    @Override
    public void setup() {
        getAbstractSession().beginTransaction();
        phoneNumberQuery = new ReadObjectQuery();
        phoneNumbersQuery = new ReadAllQuery();
        phoneNumberQuery.setReferenceClass(PhoneNumber.class);
        phoneNumbersQuery.setReferenceClass(PhoneNumber.class);
        Expression exp = new ExpressionBuilder().get("owner").get("firstName").equal("Bob");
        phoneNumberQuery.setSelectionCriteria(exp);
        phoneNumbersQuery.setSelectionCriteria(exp);
        phoneNumberQuery.conformResultsInUnitOfWork();
        phoneNumbersQuery.conformResultsInUnitOfWork();

        contactsQuery = new ReadAllQuery();
        contactsQuery.setReferenceClass(Contact.class);
        exp = new ExpressionBuilder().get("mailAddress").get("mailAddress").like("t%");
        contactsQuery.setSelectionCriteria(exp);
        contactsQuery.conformResultsInUnitOfWork();
    }

    @Override
    public void reset() {
        getAbstractSession().rollbackTransaction();
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }

    @Override
    public void test() {
        testThrowNoConformException();
        testThrowConformExceptionWithIndirection();
        testThrowConformExceptionInAllCases();
    }

    protected void setupTrial(int value) {
        pass = false;
        uow = getSession().acquireUnitOfWork();
        uow.setShouldThrowConformExceptions(value);
    }

    protected void tearDownTrial() {
        uow.release();
    }

    protected void testThrowNoConformException() {
        // First test the default behavior.
        setupTrial(UnitOfWorkImpl.DO_NOT_THROW_CONFORM_EXCEPTIONS);
        changeBobToFred();
        try {
            String owner = getAPhoneNumberOfBob().getOwner().getFirstName();
            if (owner.equals("Fred")) {
                // The default behavior should be like this.
            } else {
                throw new TestErrorException("The first name was not conformed to UOW changes: " + owner);
            }
        } catch (Exception e) {
            throw new TestErrorException("An exception should not be thrown in the default case: " + e);
        } finally {
            tearDownTrial();
        }
    }

    protected void testThrowConformExceptionWithIndirection() {
        // First test that an exception is thrown with indirection and an update.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        changeBobToFred();
        try {
            getAPhoneNumberOfBob();
        } catch (QueryException e) {
            // This is the excpected behavior.
            pass = true;
        } finally {
            tearDownTrial();
        }
        if (!pass) {
            throw new TestErrorException("A conforming query exception should have been thrown in update case.");
        }

        // Second test that an exception is thrown with indirection and a deletion.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        deleteBob();
        try {
            getAPhoneNumberOfBob();
        } catch (QueryException e) {
            // This is the expected behavior.
            pass = true;
        } finally {
            tearDownTrial();
        }
        if (!pass) {
            throw new TestErrorException("A conforming query exception should have been thrown in delete case.");
        }

        // Third test that an exception is thrown with indirection and an insertion.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        addPhoneNumberToBob();
        try {
            getAPhoneNumberOfBob();
        } catch (QueryException e) {
            // This is the expected behavior.
            pass = true;
        } finally {
            tearDownTrial();
        }
        if (!pass) {
            throw new TestErrorException("A conforming query exception should be thrown in insertion case.");
        }

        // Fourth test that an exception is thrown for a readObjectQuery with Indirection.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        changeBobToFred();
        try {
            getASinglePhoneNumberOfBob();
        } catch (QueryException e) {
            // This is the excpected behavior.
            pass = true;
        } finally {
            tearDownTrial();
        }
        if (!pass) {
            throw new TestErrorException("A conforming query exception should have been thrown in read single object case.");
        }

        // Fifth test that an exception is not thrown when indirection is not used.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        changeAMailAddress();
        try {
            getContacts();
        } catch (QueryException e) {
            throw new TestErrorException("A conforming query exception should not have be thrown when indirection not used.");
        } finally {
            tearDownTrial();
        }
    }

    protected void testThrowConformExceptionInAllCases() {
        // First test that an exception is thrown with an update.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        changeBobToFred();
        try {
            getAPhoneNumberOfBob();
        } catch (QueryException e) {
            // This is the excpected behavior.
            pass = true;
        } finally {
            tearDownTrial();
        }
        if (!pass) {
            throw new TestErrorException("A conforming query exception should have been thrown with an update.");
        }

        // Second test that an exception is thrown even in a case without indirection.
        setupTrial(UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS);
        changeAMailAddress();
        try {
            Vector v = getContacts();
            String s = "";
            if (v.size() > 0) {
                Contact contact = (Contact)v.firstElement();
                s = contact.getMailAddress().mailAddress;
            }
            throw new TestErrorException("A conforming query exception should have been thrown even when indirection not involved: " +
                                         s + v.size());
        } catch (QueryException e) {
            // This is the expected behavior.
        } finally {
            tearDownTrial();
        }
    }

    private void changeBobToFred() {
        Expression exp = new ExpressionBuilder().get("firstName").equal("Bob");
        bob = (Employee)uow.readObject(Employee.class, exp);
        bob.setFirstName("Fred");
    }

    private void deleteBob() {
        Expression exp = new ExpressionBuilder().get("firstName").equal("Bob");
        bob = (Employee)uow.readObject(Employee.class, exp);
        uow.deleteObject(bob);
    }

    private void addPhoneNumberToBob() throws QueryException {
        PhoneNumber phoneNumber = (PhoneNumber)uow.newInstance(PhoneNumber.class);
        bob.addPhoneNumber(phoneNumber);
        phoneNumber.setOwner(bob);
    }

    private PhoneNumber getAPhoneNumberOfBob() throws QueryException {
        Vector phoneNumbers = (Vector)uow.executeQuery(phoneNumbersQuery);
        return (PhoneNumber)phoneNumbers.firstElement();
    }

    private PhoneNumber getASinglePhoneNumberOfBob() throws QueryException {
        return (PhoneNumber)uow.executeQuery(phoneNumberQuery);
    }

    private void changeAMailAddress() {
        Expression exp = new ExpressionBuilder().get("mailAddress").equal("three@object.com");
        MailAddress mailAddress = (MailAddress)uow.readObject(MailAddress.class, exp);
        mailAddress.mailAddress = new String("four@object.com");
    }

    private Vector getContacts() throws QueryException {
        return (Vector)uow.executeQuery(contactsQuery);
    }
}
