/*
 * 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 java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.queries.UpdateAllQuery;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.queries.ReportQueryResult;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.expressions.DataExpression;

public class UpdateAllQueryTestHelper {

    public static String execute(Session mainSession, Class referenceClass, HashMap updateClauses, Expression selectionExpression) {
        return execute(mainSession, referenceClass, updateClauses, selectionExpression, true);
    }

    public static String execute(Session mainSession, Class referenceClass, HashMap updateClauses, Expression selectionExpression, boolean handleChildren) {
        return execute(mainSession, createUpdateAllQuery(referenceClass, updateClauses, selectionExpression), true);
    }

    public static String execute(Session mainSession, UpdateAllQuery uq) {
        return execute(mainSession, uq,  true);
    }

    // Compares results of updating multiple objects yusing traditionalTopLink update one-by-one approach
    // with updating using UpdateAllQuery. If results differ retuns a non-null error message.
    // To use this method:
    // 1. Populate db with the objects on which update should be performed;
    // 2. In case handleChildren == true the similar query will also be tested with all subclasses:
    //      example: for uq.referenceClass()==Project, the test will also run for SmallProject and LargeProject.
    // 3. After the test is completed it leaves the db in the original state (uses rollbacks).
    public static String execute(Session mainSession, UpdateAllQuery uq,  boolean handleChildren) {
        // Find the inheritance root class - the test will compare all instances of this class
        // after traditional TopLink update (one-by-one) with all instances of this class
        // after UpdateAllQuery. The test succeeds if the two collections are equal.
        Class rootClass = uq.getReferenceClass();
        ClassDescriptor descriptor = mainSession.getClassDescriptor(uq.getReferenceClass());
        if(descriptor.hasInheritance()) {
            ClassDescriptor parentDescriptor = descriptor;
            while(!parentDescriptor.getInheritancePolicy().isRootParentDescriptor()) {
                parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor();
            }
            rootClass = parentDescriptor.getJavaClass();
        }

        String errorMsg = execute(mainSession, uq, handleChildren, rootClass);

        if(errorMsg.length() == 0) {
            return null;
        } else {
            return errorMsg;
        }
    }

    protected static String execute(Session mainSession, UpdateAllQuery uq, boolean handleChildren,
                                  Class rootClass) {
        String errorMsg = "";
        ClassDescriptor descriptor = mainSession.getDescriptor(uq.getReferenceClass());

        clearCache(mainSession);

        // original objects
        Vector objects = mainSession.readAllObjects(rootClass);

        // first update using the original TopLink approach - one by one.
        // That will be done using report query - it will use the same selection criteria
        // as UpdateAllQuery and each attribute will correspond to an update item.
        ReportQuery rq = new ReportQuery(uq.getReferenceClass(), uq.getExpressionBuilder());
        rq.setSelectionCriteria(uq.getSelectionCriteria());
        rq.setShouldRetrievePrimaryKeys(true);
        // some db platforms don't allow nulls in select clause - so add the fields with null values to the query result.
        Vector fieldsWithNullValues = new Vector();
        Iterator itEntrySets = uq.getUpdateClauses().entrySet().iterator();
        while(itEntrySets.hasNext()) {
            Map.Entry entry = (Map.Entry)itEntrySets.next();
            Expression valueExpression;
            String keyString = getQualifiedFieldNameFromKey(entry.getKey(), rq.getReferenceClass(), descriptor, mainSession);
            Object value = entry.getValue();
            DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForField(new DatabaseField(keyString));
            if(mapping != null && mapping.isOneToOneMapping() && value != null) {
                // Note that this only works in case the reference PK is not compound
                if(((OneToOneMapping)mapping).getSourceToTargetKeyFields().size() > 1) {
                    errorMsg = "Attribute "+ mapping.getAttributeName() + " mapped with 1to1 mapping that has more than one targetKeyField. UpdateAllQueryTestHelper currently doesn't support that.";
                }
                DatabaseField targetField = ((OneToOneMapping)mapping).getSourceToTargetKeyFields().get(new DatabaseField(keyString));
                if(value instanceof Expression) {
                    valueExpression = ((Expression)(((Expression)value).clone())).getField(targetField);
                } else {
                    ClassDescriptor targetDescriptor = mapping.getReferenceDescriptor();
                    Object fieldValue = targetDescriptor.getObjectBuilder().extractValueFromObjectForField(value, targetField, (org.eclipse.persistence.internal.sessions.AbstractSession)mainSession);
                    valueExpression = rq.getExpressionBuilder().value(fieldValue);
                }
            } else {
                if(value instanceof Expression) {
                    valueExpression = (Expression)value;
                } else {
                    valueExpression = rq.getExpressionBuilder().value(value);
                }
            }
            if(value == null) {
                fieldsWithNullValues.add(keyString);
            } else {
                rq.addAttribute(keyString, valueExpression);
            }
        }

        UnitOfWork uow = mainSession.acquireUnitOfWork();
        // mainSession could be a ServerSession
        Session session = uow.getParent();

        // report query results contain the values to be assigned for each object to be updated.
        Vector result = (Vector)session.executeQuery(rq);
        Vector objectsAfterOneByOneUpdate = new Vector(objects.size());
        ((org.eclipse.persistence.internal.sessions.AbstractSession)session).beginTransaction();
        try {
            for (int i = 0; i < result.size(); i++) {
                // read through uow the object(clone) to be updated
                ReportQueryResult reportResult = (ReportQueryResult)result.elementAt(i);
                // hammer into the object the updated values
                Object obj = reportResult.readObject(rq.getReferenceClass(), uow);
                DatabaseRecord row = new DatabaseRecord();
                for (int j = 0; j < reportResult.getNames().size(); j++) {
                    String name = reportResult.getNames().get(j);
                    DatabaseField field = new DatabaseField(name);
                    Object value = reportResult.getResults().get(j);
                    row.add(field, value);
                }
                // some db platforms don't allow nulls in select clause - so add the fields with null values to the query result
                for (int j = 0; j < fieldsWithNullValues.size(); j++) {
                    String name = (String)fieldsWithNullValues.elementAt(j);
                    DatabaseField field = new DatabaseField(name);
                    row.add(field, null);
                }
                rq.getDescriptor().getObjectBuilder().assignReturnRow(obj, (AbstractSession)uow, row, null);
            }
            // uow committed - objects updated.
            uow.commit();

            // Because the transaction will be rolled back (to return to the original state to execute UpdateAllQuery)
            // objects are copied into another vector - later it will be compared with UpdateAllQuery result.
            for(int i=0; i < objects.size(); i++) {
                Object original = objects.elementAt(i);
                Object copy = buildCopy(descriptor, original, uow);
                objectsAfterOneByOneUpdate.add(copy);
            }
        } finally {
            // transaction rolled back - objects back to the original state in the db.
            ((org.eclipse.persistence.internal.sessions.AbstractSession)session).rollbackTransaction();
        }
        clearCache(mainSession);

        // now use UpdateAllQuery
        uow = mainSession.acquireUnitOfWork();
        // mainSession could be a ServerSession
        session = uow.getParent();
        Vector objectsAfterUpdateAll = new Vector(objects.size());
        ((org.eclipse.persistence.internal.sessions.AbstractSession)session).beginTransaction();
        try {
            uow.executeQuery(uq);
            // uow committed - objects updated.
            uow.commit();

            // Because the transaction will be rolled back (to return to the original state)
            // objects are copied into another vector - it will be compared with update one-by-one result.
            for(int i=0; i < objects.size(); i++) {
                Object original = objects.elementAt(i);
                Object copy = buildCopy(descriptor, original, uow);
                objectsAfterUpdateAll.add(copy);
            }
        } finally {
            // transaction rolled back - objects back to the original state in the db.
            ((org.eclipse.persistence.internal.sessions.AbstractSession)session).rollbackTransaction();
        }
        clearCache(mainSession);

        // verify
        String classErrorMsg = "";
        for(int i=0; i < objects.size(); i++) {
            Object obj = objects.elementAt(i);
            Object obj1 = objectsAfterOneByOneUpdate.elementAt(i);
            Object obj2 = objectsAfterUpdateAll.elementAt(i);
            boolean equal = rq.getDescriptor().getObjectBuilder().compareObjects(obj, obj2, (org.eclipse.persistence.internal.sessions.AbstractSession)session);
            if(!equal) {
                classErrorMsg = classErrorMsg + "Difference: original = " + obj.toString() + "; afterOneByOneUpdate = " + obj1.toString() +"; afterUpdateAll = " + obj2.toString() + ";";
            }
        }
        if(classErrorMsg.length() > 0) {
            errorMsg = errorMsg + classErrorMsg;
        }

        if(handleChildren) {
            if(descriptor.hasInheritance() && descriptor.getInheritancePolicy().hasChildren()) {
                Iterator it = descriptor.getInheritancePolicy().getChildDescriptors().iterator();
                while(it.hasNext()) {
                    ClassDescriptor childDescriptor = (ClassDescriptor)it.next();
                    Class childReferenceClass = childDescriptor.getJavaClass();
                    UpdateAllQuery childUq = (UpdateAllQuery)uq.clone();
                    childUq.setReferenceClass(childReferenceClass);
                    childUq.setIsPrepared(false);
                    errorMsg += execute(mainSession, childUq, handleChildren, rootClass);
                }
            }
        }
        return errorMsg;
    }

    protected static void clearCache(Session mainSession) {
        mainSession.getIdentityMapAccessor().initializeAllIdentityMaps();
    }

    public static UpdateAllQuery createUpdateAllQuery(Class referenceClass, HashMap updateClauses, Expression selectionExpression) {
        // Construct UpdateAllQuery
        UpdateAllQuery uq = new UpdateAllQuery(referenceClass, selectionExpression);
        Iterator itEntrySets = updateClauses.entrySet().iterator();
        while(itEntrySets.hasNext()) {
            Map.Entry entry = (Map.Entry)itEntrySets.next();
            uq.addUpdate((String)entry.getKey(), entry.getValue());
        }
        return uq;
    }

    static protected Object buildCopy(ClassDescriptor descriptor, Object original, UnitOfWork uow) {
        Object copy = descriptor.getCopyPolicy().buildClone(original, uow);
        descriptor.getObjectBuilder().copyInto(original, copy, true);
        return copy;
    }

    static protected String getQualifiedFieldNameFromKey(Object key, Class referenceClass, ClassDescriptor descriptor, Session session) {
        DatabaseField field = null;
        if(key instanceof String) {
            // attribute name
            String name = (String)key;
            DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(name);
            if(mapping != null) {
                field = mapping.getFields().firstElement();
            }
        } else if(key instanceof DataExpression) {
            DataExpression fieldExpression = (DataExpression)key;
            field = descriptor.getObjectBuilder().getFieldForQueryKeyName(fieldExpression.getName());
            if(field == null) {
                DataExpression fieldExpressionClone = (DataExpression)fieldExpression.clone();
                fieldExpressionClone.getBuilder().setQueryClass(referenceClass);
                fieldExpressionClone.getBuilder().setSession((org.eclipse.persistence.internal.sessions.AbstractSession)session);
                field = fieldExpressionClone.getField();
            }
        }

        if(field != null) {
            return field.getQualifiedName();
        }

        // should never happen
        return null;
    }
}
