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

import java.util.*;

import org.eclipse.persistence.tools.schemaframework.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;

/**
 * This stored procedure generator is meant to generate INSERT and UPDATE
 * procedures that return values, but currently only generates
 * procedures that just perform the INSERT/UPDATE, so is not currently used.
 * It will hopefully be finished at some point...
 */
public class StoredProcedureGeneratorForAdapter extends StoredProcedureGenerator {

    public StoredProcedureGeneratorForAdapter(SchemaManager schemaMngr) {
        super(schemaMngr);
        insertStoredProcedures = new Hashtable();
        updateStoredProcedures = new Hashtable();
        substituteName = new Hashtable();
    }

    protected Hashtable insertStoredProcedures;
    protected Hashtable updateStoredProcedures;
    protected Hashtable substituteName;
    protected boolean useTableNames;

    public boolean usesTableNames() {
        return useTableNames;
    }

    public void setUseTableNames(boolean useTableNames) {
        this.useTableNames = useTableNames;
    }

    /**
     * PUBLIC:
     * Inspired by StoredProcedureGenerator.generateStoredProcedures though
     * uses another attribute (insertStoredProcedures) and doesn't write definitions
     */
    public void generateInsertStoredProceduresDefinitionsForProject(Project project) {
        verifyProject(project);
        Map descrpts = project.getDescriptors();
        Iterator iterator = descrpts.keySet().iterator();
        ClassDescriptor desc;
        while (iterator.hasNext()) {
            desc = (ClassDescriptor)descrpts.get(iterator.next());
            if (desc.isDescriptorForInterface() || desc.isAggregateDescriptor()) {
                continue;
            }
            if (!desc.getQueryManager().hasInsertQuery()) {
                InsertObjectQuery insertQuery = new InsertObjectQuery();
                insertQuery.setModifyRow(desc.getObjectBuilder().buildTemplateInsertRow(getSession()));
                desc.getQueryManager().setInsertQuery(insertQuery);
            }
            StoredProcedureDefinition definition = generateStoredProcedureDefinition(desc, desc.getQueryManager().getInsertQuery(), "INS_");
            insertStoredProcedures.put(desc, definition);
        }
    }

    public void generateUpdateStoredProceduresDefinitionsForProject(Project project) {
        verifyProject(project);
        Map descrpts = project.getDescriptors();
        Iterator iterator = descrpts.keySet().iterator();
        ClassDescriptor desc;
        while (iterator.hasNext()) {
            desc = (ClassDescriptor)descrpts.get(iterator.next());
            if (desc.isDescriptorForInterface() || desc.isAggregateDescriptor()) {
                continue;
            }
            if (!desc.getQueryManager().hasUpdateQuery()) {
                UpdateObjectQuery updateQuery = new UpdateObjectQuery();
                updateQuery.setModifyRow(desc.getObjectBuilder().buildTemplateUpdateRow(getSession()));
                if (updateQuery.getModifyRow().size() > 0) {
                    desc.getQueryManager().setUpdateQuery(updateQuery);
                }
            }
            if (desc.getQueryManager().getUpdateQuery() != null) {
                StoredProcedureDefinition definition = generateStoredProcedureDefinition(desc, desc.getQueryManager().getUpdateQuery(), "UPD_");
                updateStoredProcedures.put(desc, definition);
            }
        }
    }

    protected StoredProcedureDefinition generateStoredProcedureDefinition(ClassDescriptor desc, DatabaseQuery query, String namePrefix) {
        Vector fields = desc.getFields();
        Hashtable namesNewToNames = null;
        if (shouldCapitalizeNames()) {
            namesNewToNames = new Hashtable();
            fields = capitalize(fields, namesNewToNames);
        }
        StoredProcedureDefinition definition = generateObjectStoredProcedure(query, fields, namePrefix);
        if (namesNewToNames != null && !namesNewToNames.isEmpty()) {
            substituteName.put(definition, namesNewToNames);
        }
        return definition;
    }

    public void generateStoredProceduresDefinitionsForProject(Project project) {
        generateInsertStoredProceduresDefinitionsForProject(project);
        generateUpdateStoredProceduresDefinitionsForProject(project);
    }

    /**
     * PUBLIC:
     */
    public void writeInsertStoredProcedures() {
        Enumeration descriptorEnum = insertStoredProcedures.keys();
        while (descriptorEnum.hasMoreElements()) {
            ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
            StoredProcedureDefinition definition = (StoredProcedureDefinition)insertStoredProcedures.get(descriptor);
            writeDefinition(definition);
        }
    }

    public void writeUpdateStoredProcedures() {
        Enumeration descriptorEnum = updateStoredProcedures.keys();
        while (descriptorEnum.hasMoreElements()) {
            ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
            StoredProcedureDefinition definition = (StoredProcedureDefinition)updateStoredProcedures.get(descriptor);
            writeDefinition(definition);
        }
    }

    public void writeStoredProcedures() {
        writeInsertStoredProcedures();
        writeUpdateStoredProcedures();
    }

    /**
     * INTERNAL:
     * The base class doesn't allow optimistic locking in getSession().getProject() -
     * override this restriction.
     */
    @Override
    protected void verify() throws org.eclipse.persistence.exceptions.ValidationException {
    }

    /**
     * INTERNAL:
     * The base class doesn't allow optimistic locking in the project.
     */
    protected void verifyProject(Project project) {
        if (project.usesOptimisticLocking()) {
            throw org.eclipse.persistence.exceptions.ValidationException.optimisticLockingNotSupportedWithStoredProcedureGeneration();
        }
    }

    /**
     * PUBLIC:
     * Amends descriptors with stored procedures
     */
    public void amendDescriptorsInsertQuery() {
        Enumeration descriptorEnum = insertStoredProcedures.keys();
        while (descriptorEnum.hasMoreElements()) {
            ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
            StoredProcedureDefinition definition = (StoredProcedureDefinition)insertStoredProcedures.get(descriptor);
            InsertObjectQuery insertQuery = new InsertObjectQuery();
            defineQuery(insertQuery, definition);
            descriptor.getQueryManager().setInsertQuery(insertQuery);
        }
    }

    public void amendDescriptorsUpdateQuery() {
        Enumeration descriptorEnum = updateStoredProcedures.keys();
        while (descriptorEnum.hasMoreElements()) {
            ClassDescriptor descriptor = (ClassDescriptor)descriptorEnum.nextElement();
            StoredProcedureDefinition definition = (StoredProcedureDefinition)updateStoredProcedures.get(descriptor);
            UpdateObjectQuery updateQuery = new UpdateObjectQuery();
            descriptor.getQueryManager().setUpdateQuery(updateQuery);
        }
    }

    public void defineQuery(DatabaseQuery query, StoredProcedureDefinition definition) {
        Hashtable namesNewToNames = (Hashtable)substituteName.get(definition);
        query.setShouldBindAllParameters(true);
        StoredProcedureCall call = new StoredProcedureCall();
        call.setProcedureName(definition.getName());
        for (int i = 0; i < definition.getArguments().size(); i++) {
            FieldDefinition fieldDefinition = ((FieldDefinition)definition.getArguments().elementAt(i));
            String procedureParameterName = fieldDefinition.getName();
            String fieldName = getFieldName(fieldDefinition.getName());
            String argumentFieldName = fieldName;
            if (namesNewToNames != null) {
                String fieldNameOriginal = (String)namesNewToNames.get(fieldName);
                if (fieldNameOriginal != null) {
                    argumentFieldName = fieldNameOriginal;
                }
            }
            call.addNamedArgument(procedureParameterName, argumentFieldName);
        }
        query.setCall(call);
    }

    public void amendDescriptors() {
        amendDescriptorsInsertQuery();
        amendDescriptorsUpdateQuery();
    }

    // Need for capitalization is caused by bug3172139:
    // ORACLE CONNECTION METADATA.GETCOLUMNS FAILS IF PASSED LOWER-CASE NAMES
    // In case the bug is fixed, there would be no need for returning newFields.
    // However namesCapitalizedToNames still will be needed, because the DatabaseField's
    // name to be used as a parameter for StoredProcedureCall is extracted from
    // storedProcedureDefinition - and there it is always the same as in database.

    protected Vector capitalize(Vector fields, Hashtable namesCapitalizedToNames) {
        // Can't change names of descriptor's fields, create a new Vector.
        Vector newFields = null;
        for (int i = 0; i < fields.size(); i++) {
            DatabaseField field = (DatabaseField)fields.elementAt(i);
            String fieldNameUpper = field.getName().toUpperCase();
            String tableNameUpper = field.getTableName().toUpperCase();
            if (!fieldNameUpper.equals(field.getName()) || !tableNameUpper.equals(field.getTableName())) {
                DatabaseField newField = new DatabaseField(fieldNameUpper, tableNameUpper);
                newField.setType(field.getType());
                if (newFields == null) {
                    newFields = (Vector)fields.clone();
                }
                newFields.set(i, newField);
                namesCapitalizedToNames.put(fieldNameUpper, field.getName());
            }
        }
        if (newFields == null) {
            return fields;
        } else {
            return newFields;
        }
    }

    protected boolean shouldCapitalizeNames() {
        return getSession().getPlatform().isOracle();
    }

    protected String shortClassName(String originalClassName, int numberOfPackagesToIncludeIntoShortName) {
        int nLastIndex = originalClassName.length() - 1;
        for (int i = 0; i <= numberOfPackagesToIncludeIntoShortName && nLastIndex > 0; i++) {
            nLastIndex = originalClassName.lastIndexOf('.', nLastIndex - 1);
        }
        if (nLastIndex < 0 || nLastIndex == originalClassName.length() - 1) {
            return new String(originalClassName);
        } else {
            return originalClassName.substring(nLastIndex + 1);
        }
    }

    protected StoredProcedureDefinition generateObjectStoredProcedure(DatabaseQuery query, Vector fields, String namePrefix) {
        String namePrefixToUse = namePrefix;
        String className = Helper.getShortClassName(query.getDescriptor().getJavaClass());
        if (useTableNames) {
            String tableName = query.getDescriptor().getTableName();
            if (!compareNames(className, tableName)) {
                namePrefixToUse = namePrefix + tableName + "_";
            }
        }
        return generateStoredProcedure(query, fields, getPrefix() + namePrefixToUse + className);
    }

    protected boolean compareNames(String name1, String name2) {
        if (shouldCapitalizeNames()) {
            return name1.equalsIgnoreCase(name2);
        } else {
            return name1.equals(name2);
        }
    }
}
