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

import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.server.ClientSession;
import org.eclipse.persistence.descriptors.*;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.mappings.foundation.*;

/**
 * <p>
 * <b>Purpose</b>: Define a generic test for writing an object to the database.
 * Should originalObject contain no changes to the original object from the
 * database (a TRIVIAL UPDATE), find and mutate a direct to field mapping before
 * writing the object to the database.  If originalObject is different from but
 * has the same primary key as an object on the database, do not mutate the
 * object as it has already been changed (a NON-TRIVIAL UPDATE).
 * <p>
 * <b>Responsibilities</b>:
 * <ul>
 * <li> Be independent of the class being tested.
 * <li> Attempt to mutate a Direct to Field mapping if instructed to do so.
 * <li> Execute the insert object query and verify no errors occurred.
 * <li> Verify the object written matches the object that was written.
 * </ul>
 */
public class WriteObjectTest extends TransactionalTestCase {

    /** Query to read the original object from the database */
    protected ReadObjectQuery query;

    /** The original object that is set thru example methods from the model */
    protected Object originalObject;

    /** The originalObject is read from the database and stored here */
    protected Object objectToBeWritten;

    /** The object from the database is read in verify to compare against the
    * objectToBeWritten.
    */
    protected Object objectFromDatabase;

    /** The following allows individual tests to be run with or
     * without bind all parameters on. */
    protected Boolean bindAllParameters = null;
    protected Boolean bindAllParametersOriginal = null;

    /** An option to test non-trivial updates. */
    protected boolean makesTrivialUpdate = true;

    /** This determines whether the test should attempt to mutate the object.
     * This defaults to true.  It can be set to false where changing the object
     * will cause failures.
     */
    protected boolean testShouldMutate = true;

    public WriteObjectTest() {
        setDescription("The test writing of the intended object from the "+
            "database and checks if it was inserted properly");
    }

    public WriteObjectTest(Object originalObject) {
        this.originalObject = originalObject;
        setName(getName() + "(" + originalObject.getClass() + ")");
        setDescription(
            "The test writing of the intended object, '"+originalObject
            +"', from the database and checks if it was inserted properly");
    }

    public Object getOriginalObject() {
        return originalObject;
    }

    /**
     * A method that takes an object and attempts to find a direct to field
     * mapping that can be mutated.  The value of the mapping is changed by
     * appending a mutation string to the existing value in the mapping.
     * Should no suitable mapping be found, the method simply returns the
     * object passed in.
     * This covers test case bug 2773036
     */
    public Object findAndMutateDirectToFieldMappingInObject(Object objectToBeMutated, boolean isInUOW) {
        DatabaseMapping dbMapping = null;
        DatabaseMapping mutatableMapping = null;

        String mutationString = "M"; // The string to append

        /**
         * Here the class of the object passed is used to get the corresponding
         * descriptor, which is then used to find the mappings and determine if
         * one exists that can be mutated
         */
        Class objectClass = objectToBeMutated.getClass();
        ClassDescriptor descriptor = getSession().getProject().getClassDescriptor(objectClass);
        java.util.Vector mappings = descriptor.getMappings();

        if (isInUOW) {
            mutationString += "U";
        }

        java.util.Enumeration en = mappings.elements();

        /**
         * Parse the mappings for the object's descriptor to find a suitable
         * mapping that can be mutated.  The mapping must meet the conditions:
         * Not a primary key mapping
         * Must be direct to field
         * Must be a string field
         * Must not have a converter (i.e. Male-->M, Female-->F, Unknown-->U)
         * The loop exits once an appropriate mapping is found or the list of
         * mappings has been fully parsed (whichever occurs first)
         */
        while (en.hasMoreElements ()) {
            dbMapping = (DatabaseMapping) en.nextElement();

            if (!dbMapping.isPrimaryKeyMapping()
                    && dbMapping.isDirectToFieldMapping()
                    &&!((AbstractDirectMapping) dbMapping).hasConverter()
                    && (dbMapping.getAttributeAccessor().getAttributeClass())
                        .getName().indexOf("String") != -1) {
                mutatableMapping = dbMapping;
                break;
            }
        }

        /**
         * If a mapping was found that can be mutated, use TopLink methods to
         * modify the value stored in the object for that mapping.  Otherwise
         * do nothing.
         */
        if (mutatableMapping != null) {
            mutatableMapping.setAttributeValueInObject(
                objectToBeMutated,
                mutatableMapping.getAttributeValueFromObject(
                    objectToBeMutated) + mutationString);
        }
        else {
            // Can't necessarily throw error/warning as some projects
            // (i.e. LOB project) have descriptors that are not simple to mutate
        }

        return objectToBeMutated;
    }

    /**
     * @see #setMakesTrivialUpdate(boolean)
     */
    public boolean makesTrivialUpdate() {
        return makesTrivialUpdate;
    }

    /**
     * @see #setTestShouldMutate(boolean)
     */
    public boolean testShouldMutate() {
        return testShouldMutate;
    }

    @Override
    public void reset() {
        if (bindAllParametersOriginal != null) {
            getSession().getLogin().setShouldBindAllParameters(bindAllParametersOriginal.booleanValue());
        }
        super.reset();
    }

    /**
     * A trivial update is writing the same version of an object to the
     * database as exists on the database.  Normally in this test the object
     * passed to the constructor is used only to read the version of itself on
     * the database.  This version from the database is then written to the
     * database: a trivial update.  If this flag is set and originalObject is
     * different from but has the same primary key as an object on the database,
     * then a non-trivial update will occur.
     * Warning: If you modify the objects passed to this
     * test, do not obtain them from the population manager, as they may become
     * corrupted for other users.
     */
    public void setMakesTrivialUpdate(boolean value) {
        this.makesTrivialUpdate = value;
    }

    /**
     * Some subclasses of WriteObjectTest will not return the correct results if
     * the object is mutated, for example tests that pass null values and expect
     * nulls to be returned.  If this flag is set then the object will not be
     * mutated before attempting to write to the database.
     */
    public void setTestShouldMutate(boolean value) {
        this.testShouldMutate = value;
    }

    /**
     * Allows one to set bindAllParameters to true on a test by test basis.
     * This works only for simple sessions, and could cause this simple test to
     * run much slower than before.
     */
    public void setShouldBindAllParameters(boolean value) {
        bindAllParameters = Boolean.valueOf(value);
    }

    @Override
    protected void setup() {
        if (shouldBindAllParameters() != null) {
            bindAllParametersOriginal = Boolean.valueOf(getSession().getLogin().shouldBindAllParameters());
            getSession().getLogin().setShouldBindAllParameters(shouldBindAllParameters().booleanValue());
        }
        super.setup();

        this.query = new ReadObjectQuery();
        this.query.setSelectionObject(this.originalObject);

        /* Must ensure that the object is from the database for updates. */
        this.objectToBeWritten = getSession().executeQuery(this.query);
        if (this.query.getDescriptor().shouldIsolateProtectedObjectsInUnitOfWork() && getSession().isClientSession()){
            //must get entity from server session and not the isolated session.
            this.objectToBeWritten = ((ClientSession)getSession()).getParent().getIdentityMapAccessor().getFromIdentityMap(this.objectToBeWritten);
        }
        if (this.objectToBeWritten == null) {
            this.objectToBeWritten = this.originalObject;
            this.query = new ReadObjectQuery();
            this.query.setSelectionObject(this.originalObject);
        }

        if (!makesTrivialUpdate()) {
            this.objectToBeWritten = this.originalObject;
        }
    }

    public Boolean shouldBindAllParameters() {
        return bindAllParameters;
    }


    /**
     * The test() method will, if required, pass the object to the
     * findAndMutateDirectToFieldMappingInObject method, and will then attempt
     * to write the object to the database.
     */
    @Override
    protected void test() {

        if (makesTrivialUpdate() && testShouldMutate()) {
            // Only want to do this if the update is trivial
            // Otherwise there are already changes in the object that
            // will generate SQL
            this.objectToBeWritten =
                this.findAndMutateDirectToFieldMappingInObject(
                    this.objectToBeWritten, false);
        }

        getDatabaseSession().writeObject(this.objectToBeWritten);
    }

    /**
     * Verify if the objects match completely through allowing the session
     * to use the descriptors.  This will compare the objects and all of
     * their privately owned parts.
     */
    @Override
    protected void verify() {
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
        this.objectFromDatabase = getSession().executeQuery(this.query);

        if (!(compareObjects(this.objectToBeWritten, this.objectFromDatabase))) {
            throw new TestErrorException("The object inserted into the database, '"
                + this.objectFromDatabase + "' does not match the original, '"
                + this.objectToBeWritten + "'.");
        }
    }
}
