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

import java.io.Serializable;
import java.util.*;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.queries.*;

/**
 * <p><b>Purpose</b>:
 * Allows for INSERT or UPDATE operations to return values back into the object being written.
 * This allows for table default values, trigger or stored procedures computed values to be set back
 * into the object.
 * This can be used with generated SQL on the Oracle platform using the RETURNING clause,
 * or through stored procedures on other platforms.
 *
 * @since TopLink 10.1.3
 */
public class ReturningPolicy implements Serializable, Cloneable {
    protected static final int INSERT = 0;
    protected static final int UPDATE = 1;
    protected static final int NUM_OPERATIONS = 2;
    protected static final int RETURN_ONLY = 0;
    protected static final int WRITE_RETURN = 1;
    protected static final int MAPPED = 2;
    protected static final int UNMAPPED = 3;
    protected static final int ALL = 4;
    protected static final int MAIN_SIZE = 5;

    /** owner of the policy */
    protected ClassDescriptor descriptor;

    /**
     * Stores an object of type Info for every call to any of addField.. methods.
     * Should be filled out before initialize() is called:
     * fields added after initialization are ignored.
     */
    protected List<Info> infos = new ArrayList<>();

    /**
     * The following attributes are initialized by initialize() method.
     * Contains the actual DatabaseFields to be returned.
     * Populated during descriptor initialization using infos.
     * Here's the order:
     * <pre>
     * main[INSERT][RETURN_ONLY]  main[INSERT][WRITE_RETURN]  main[INSERT][MAPPED]    main[INSERT][UNMAPPED]    main[INSERT][ALL]
     * main[UPDATE][RETURN_ONLY]  main[UPDATE][WRITE_RETURN]  main[UPDATE][MAPPED]    main[UPDATE][UNMAPPED]    main[UPDATE][ALL]
     * </pre>
     * After initialization main[UPDATE,WRITE_RETURN] will contain all DatabaseFields that should be
     * returned on Update as read-write.
     * <pre>
     * main[i][RETURN_ONLY] + main[i][WRITE_RETURN] = main[i][MAPPED]
     * main[i][MAPPED] + main[i][UNMAPPED] = main[i][ALL]
     * </pre>
     */
    protected Collection<DatabaseField>[][] main;

    /**
     * maps ClassDescriptor's tables into Vectors of fields to be used for call generation.
     * Lazily initialized array [NUM_OPERATIONS]
     */
    protected Map<DatabaseTable, List<DatabaseField>>[] tableToFieldsForGenerationMap;

    /** indicates whether ReturningPolicy is used for generation of the PK. */
    protected boolean isUsedToSetPrimaryKey;

    /** contains all default table the returning fields that are either unmapped or mapped supplied with types. */
    protected Map<DatabaseField, DatabaseField> fieldsNotFromDescriptor_DefaultTable;

    /** contains all the other tables returning fields that are either unmapped or mapped supplied with types. */
    protected Map<DatabaseField, DatabaseField> fieldsNotFromDescriptor_OtherTables;

    public ReturningPolicy() {
        super();
    }

    /**
     * PUBLIC:
     * Return the owner of the policy.
     */
    public ClassDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * INTERNAL:
     */
    protected void fieldIsNotFromDescriptor(DatabaseField field) {
        if (field.getTable().equals(getDescriptor().getDefaultTable())) {
            if (this.fieldsNotFromDescriptor_DefaultTable == null) {
                this.fieldsNotFromDescriptor_DefaultTable = new HashMap<>();
            }
            this.fieldsNotFromDescriptor_DefaultTable.put(field, field);
        } else {
            if (this.fieldsNotFromDescriptor_OtherTables == null) {
                this.fieldsNotFromDescriptor_OtherTables = new HashMap<>();
            }
            this.fieldsNotFromDescriptor_OtherTables.put(field, field);
        }
    }

    /**
     * INTERNAL:
     */
    public List<DatabaseField> getFieldsToGenerateInsert(DatabaseTable table) {
        return getVectorOfFieldsToGenerate(INSERT, table);
    }

    /**
     * INTERNAL:
     */
    public List<DatabaseField> getFieldsToGenerateUpdate(DatabaseTable table) {
        return getVectorOfFieldsToGenerate(UPDATE, table);
    }

    /**
     * INTERNAL:
     */
    public List<Info> getFieldInfos() {
        return infos;
    }

    /**
     * INTERNAL:
     */
    public void setFieldInfos(List<Info> infos) {
        this.infos = infos;
    }

    /**
     * INTERNAL:
     * Used for testing only
     */
    public boolean hasEqualFieldInfos(ReturningPolicy returningPolicyToCompare) {
        return hasEqualFieldInfos(returningPolicyToCompare.getFieldInfos());
    }

    /**
     * INTERNAL:
     * Used for testing only
     */
    public boolean hasEqualFieldInfos(List<Info> infosToCompare) {
        return areCollectionsEqualAsSets(getFieldInfos(), infosToCompare);
    }

    /**
     * INTERNAL:
     * Compares two Collections as sets (ignoring the order of the elements).
     * Note that the passed Collections are cloned.
     * Used for testing only.
     */
    public static boolean areCollectionsEqualAsSets(Collection<? extends Info> col1, Collection<? extends Info> col2) {
        if (col1 == col2) {
            return true;
        }
        if (col1.size() != col2.size()) {
            return false;
        }
        Collection<Info> c1 = new ArrayList<Info>(col1);
        Collection<Info> c2 = new ArrayList<>(col2);
        for (Iterator<Info> i = c1.iterator(); i.hasNext();) {
            Info o = i.next();
            c2.remove(o);
        }
        return c2.isEmpty();
    }

    /**
     * INTERNAL:
     */
    @SuppressWarnings({"unchecked"})
    protected List<DatabaseField> getVectorOfFieldsToGenerate(int operation, DatabaseTable table) {
        if (this.main[operation][ALL] == null) {
            return null;
        }
        if (this.tableToFieldsForGenerationMap == null) {
            // the method is called for the first time
            tableToFieldsForGenerationMap = (Map<DatabaseTable, List<DatabaseField>>[]) new HashMap[NUM_OPERATIONS];
        }
        if (this.tableToFieldsForGenerationMap[operation] == null) {
            // the method is called for the first time for this operation
            this.tableToFieldsForGenerationMap[operation] = new HashMap<>();
        }
        List<DatabaseField> fieldsForGeneration = this.tableToFieldsForGenerationMap[operation].get(table);
        if (fieldsForGeneration == null) {
            // the method is called for the first time for this operation and this table
            fieldsForGeneration = new ArrayList<>();
            Iterator<DatabaseField> it = this.main[operation][ALL].iterator();
            while (it.hasNext()) {
                DatabaseField field = it.next();
                if (field.getTable().equals(table)) {
                    fieldsForGeneration.add(field);
                }
            }
            this.tableToFieldsForGenerationMap[operation].put(table, fieldsForGeneration);
        }
        return fieldsForGeneration;
    }

    /**
     * INTERNAL:
     */
    public Collection<DatabaseField> getFieldsToMergeInsert() {
        return main[INSERT][MAPPED];
    }

    /**
     * INTERNAL:
     */
    public Collection<DatabaseField> getFieldsToMergeUpdate() {
        return main[UPDATE][MAPPED];
    }

    /**
     * INTERNAL:
     * Normally cloned when not yet initialized.
     * If initialized ReturningPolicy cloned then the clone should be re-initialized.
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (Exception exception) {
            throw new InternalError("clone failed");
        }
    }

    /**
     * INTERNAL:
     */
    public void setDescriptor(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an insert operation.
     */
    public void addFieldForInsert(String qualifiedName) {
        addFieldForInsert(qualifiedName, null);
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an insert operation.
     * The type may be required to bind the output parameter if not known by the mapping.
     */
    public void addFieldForInsert(String qualifiedName, Class<?> type) {
        addFieldForInsert(createField(qualifiedName, type));
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an insert operation.
     */
    public void addFieldForInsert(DatabaseField field) {
        addField(field, true, false, false);
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an insert operation.
     * A field added with addFieldForInsertReturnOnly method
     * is excluded from INSERT clause during SQL generation.
     */
    public void addFieldForInsertReturnOnly(String qualifiedName) {
        addFieldForInsertReturnOnly(qualifiedName, null);
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an insert operation.
     * A field added with addFieldForInsertReturnOnly method
     * is excluded from INSERT clause during SQL generation.
     * The type may be required to bind the output parameter if not known by the mapping.
     */
    public void addFieldForInsertReturnOnly(String qualifiedName, Class type) {
        addFieldForInsertReturnOnly(createField(qualifiedName, type));
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an insert operation.
     * A field added with addFieldForInsertReturnOnly method
     * is excluded from INSERT clause during SQL generation.
     */
    public void addFieldForInsertReturnOnly(DatabaseField field) {
        addField(field, true, true, false);
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an update operation.
     */
    public void addFieldForUpdate(String qualifiedName) {
        addFieldForUpdate(qualifiedName, null);
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an update operation.
     * The type may be required to bind the output parameter if not known by the mapping.
     */
    public void addFieldForUpdate(String qualifiedName, Class<?> type) {
        addFieldForUpdate(createField(qualifiedName, type));
    }

    /**
     * PUBLIC:
     * Define that the field will be returned from an update operation.
     */
    public void addFieldForUpdate(DatabaseField field) {
        addField(field, false, false, true);
    }

    /**
     * INTERNAL:
     */
    protected void addField(DatabaseField field, boolean isInsert, boolean isInsertModeReturnOnly, boolean isUpdate) {
        getFieldInfos().add(new Info(field, isInsert, isInsertModeReturnOnly, isUpdate));
    }

    /**
     * INTERNAL:
     */
    public static class Info implements Cloneable {
        private DatabaseField field;
        private boolean isInsert;
        private boolean isInsertModeReturnOnly;
        private boolean isUpdate;
        private Class<? extends Object> referenceClass;
        private String referenceClassName;

        Info() {
            super();
        }

        Info(DatabaseField field, boolean isInsert, boolean isInsertModeReturnOnly, boolean isUpdate) {
            this.field = field;
            if (field != null) {
                if (field.getType() != null) {
                    setReferenceClass(field.getType());
                }
            }
            this.isInsert = isInsert;
            this.isInsertModeReturnOnly = isInsertModeReturnOnly;
            this.isUpdate = isUpdate;
        }

        public DatabaseField getField() {
            return field;
        }

        public void setField(DatabaseField field) {
            this.field = field;
            if ((field.getType() == null) && (referenceClass != null)) {
                field.setType(referenceClass);
            }
        }

        public boolean isInsert() {
            return isInsert;
        }

        public void setIsInsert(boolean isInsert) {
            this.isInsert = isInsert;
        }

        public boolean isInsertModeReturnOnly() {
            return isInsertModeReturnOnly;
        }

        public void setIsInsertModeReturnOnly(boolean isInsertModeReturnOnly) {
            this.isInsertModeReturnOnly = isInsertModeReturnOnly;
        }

        public boolean isUpdate() {
            return isUpdate;
        }

        public void setIsUpdate(boolean isUpdate) {
            this.isUpdate = isUpdate;
        }

        public Class<? extends Object> getReferenceClass() {
            return referenceClass;
        }

        public void setReferenceClass(Class<?> referenceClass) {
            this.referenceClass = referenceClass;
            if (referenceClass != null) {
                this.referenceClassName = referenceClass.getName();
            }
        }

        public String getReferenceClassName() {
            return referenceClassName;
        }

        public void setReferenceClassName(String referenceClassName) {
            this.referenceClassName = referenceClassName;
        }

        // operation is INSERT or UPDATE (0 or 1)
        boolean is(int operation, int stateToCheck) {
            if (operation == INSERT) {
                if (isInsert) {
                    if (stateToCheck == RETURN_ONLY) {
                        return isInsertModeReturnOnly;
                    } else {
                        return !isInsertModeReturnOnly;
                    }
                }
            } else {
                if (isUpdate) {
                    return stateToCheck == WRITE_RETURN;
                }
            }
            return false;
        }

        // operation is INSERT or UPDATE (0 or 1)
        boolean is(int operation) {
            if (operation == INSERT) {
                return isInsert;
            } else {
                return isUpdate;
            }
        }

        /**
         * INTERNAL:
         */
        @Override
        public Object clone() {
            try {
                return super.clone();
            } catch (Exception exception) {
                throw new InternalError("clone failed");
            }
        }

        @Override
        public boolean equals(Object objectToCompare) {
            if (objectToCompare instanceof Info) {
                return equals((Info)objectToCompare);
            } else {
                return false;
            }
        }

        boolean equals(Info infoToCompare) {
            if (this == infoToCompare) {
                return true;
            }
            if (!getField().equals(infoToCompare.getField())) {
                return false;
            }
            if ((getField().getType() == null) && (infoToCompare.getField().getType() != null)) {
                return false;
            }
            if ((getField().getType() != null) && !getField().getType().equals(infoToCompare.getField().getType())) {
                return false;
            }
            if (isInsert() != infoToCompare.isInsert()) {
                return false;
            }
            if (isInsertModeReturnOnly() != infoToCompare.isInsertModeReturnOnly()) {
                return false;
            }
            if (isUpdate() != infoToCompare.isUpdate()) {
                return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            DatabaseField field = getField();
            Class<? extends Object> type = field != null ? field.getType() : null;
            boolean isInsert = isInsert();
            boolean isInsertModeReturnOnly = isInsertModeReturnOnly();
            boolean isUpdate = isUpdate();

            int result = field != null ? field.hashCode() : 0;
            result = 31 * result + (type != null ? type.hashCode() : 0);
            result = 31 * result + (isInsert ? 1 : 0);
            result = 31 * result + (isInsertModeReturnOnly ? 1 : 0);
            result = 31 * result + (isUpdate ? 1 : 0);
            return result;
        }
    }

    /**
     * INTERNAL:
     */
    // precondition: info1.field.equals(info2.field);
    static Info mergeInfos(Info info1, Info info2, AbstractSession session, ClassDescriptor descriptor) {
        boolean ok = true;

        DatabaseField fieldMerged = info1.getField();

        if (info2.getField().getType() != null) {
            if (info1.getField().getType() == null) {
                fieldMerged = info2.field;
            } else if (!info1.getField().getType().equals(info2.getField().getType())) {
                session.getIntegrityChecker().handleError(DescriptorException.returningPolicyFieldTypeConflict(info1.getField().getName(), info1.getField().getType().getName(), info2.getField().getType().getName(), descriptor));
                ok = false;
            }
        }

        boolean isInsertMerged = false;
        boolean isInsertModeReturnOnlyMerged = false;
        if (info1.isInsert() && !info2.isInsert()) {
            isInsertMerged = true;
            isInsertModeReturnOnlyMerged = info1.isInsertModeReturnOnly();
        } else if (!info1.isInsert() && info2.isInsert()) {
            isInsertMerged = true;
            isInsertModeReturnOnlyMerged = info2.isInsertModeReturnOnly();
        } else if (info1.isInsert() && info2.isInsert()) {
            isInsertMerged = true;
            isInsertModeReturnOnlyMerged = info1.isInsertModeReturnOnly();
            if (info1.isInsertModeReturnOnly() != info2.isInsertModeReturnOnly()) {
                session.getIntegrityChecker().handleError(DescriptorException.returningPolicyFieldInsertConflict(info1.getField().getName(), descriptor));
                ok = false;
            }
        }

        if (ok) {
            // merging
            boolean isUpdateMerged = info1.isUpdate() || info2.isUpdate();
            return new Info(fieldMerged, isInsertMerged, isInsertModeReturnOnlyMerged, isUpdateMerged);
        } else {
            // there is a problem - can't merge
            return null;
        }
    }

    /**
     * INTERNAL:
     */

    // used only on equal fields: field1.equals(field2)
    static protected boolean isThereATypeConflict(DatabaseField field1, DatabaseField field2) {
        return (field1.getType() != null) && (field2.getType() != null) && !field1.getType().equals(field2.getType());
    }

    /**
     * INTERNAL:
     */
    protected DatabaseField createField(String qualifiedName, Class type) {
        DatabaseField field = new DatabaseField(qualifiedName);
        field.setType(type);
        return field;
    }

    /**
     * INTERNAL:
     */
    protected Collection<DatabaseField> createCollection() {
        return new HashSet<>();
    }

    // precondition field != null
    protected void addFieldToMain(int operation, int state, DatabaseField field) {
        if (main[operation][state] == null) {
            main[operation][state] = createCollection();
        }
        main[operation][state].add(field);
    }

    protected void addCollectionToMain(int operation, int state, Collection<? extends DatabaseField> collection) {
        if ((collection == null) || collection.isEmpty()) {
            return;
        }
        if (main[operation][state] == null) {
            main[operation][state] = createCollection();
        }
        main[operation][state].addAll(collection);
    }

    protected void addMappedFieldToMain(DatabaseField field, Info info) {
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            for (int state = RETURN_ONLY; state <= WRITE_RETURN; state++) {
                if (info.is(operation, state)) {
                    addFieldToMain(operation, state, field);
                    addFieldToMain(operation, MAPPED, field);
                    addFieldToMain(operation, ALL, field);
                }
            }
        }
    }

    protected void addUnmappedFieldToMain(DatabaseField field, Info info) {
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            if (info.is(operation)) {
                addFieldToMain(operation, UNMAPPED, field);
                addFieldToMain(operation, ALL, field);
            }
        }
    }

    protected Hashtable<DatabaseField, Info> removeDuplicateAndValidateInfos(AbstractSession session) {
        Hashtable<DatabaseField, Info> infoHashtable = new Hashtable<DatabaseField, Info>();
        for (int i = 0; i < infos.size(); i++) {
            Info info1 = infos.get(i);
            info1 = (Info)info1.clone();
            DatabaseField descField = getDescriptor().buildField(info1.getField());
            if(info1.getField().getType() == null) {
                info1.setField(descField);
            } else {
                // keep the original type if specified
                info1.getField().setName(descField.getName());
                info1.getField().setTableName(getDescriptor().getDefaultTable().getQualifiedNameDelimited(session.getPlatform()));
            }
            Info info2 = infoHashtable.get(info1.getField());
            if (info2 == null) {
                infoHashtable.put(info1.getField(), info1);
            } else {
                Info infoMerged = mergeInfos(info1, info2, session, getDescriptor());
                if (infoMerged != null) {
                    // substitute info2 with infoMerged
                    infoHashtable.put(infoMerged.getField(), infoMerged);
                } else {
                    // couldn't merge info1 and info2 due to a conflict.
                    // substitute info2 with info1
                    infoHashtable.put(info1.getField(), info1);
                }
            }
        }
        return infoHashtable;
    }

    /**
     * INTERNAL:
     */
    @SuppressWarnings({"unchecked"})
    public void initialize(AbstractSession session) {
        clearInitialization();
        main = (Collection<DatabaseField>[][]) new Collection[NUM_OPERATIONS][MAIN_SIZE];

        // The order of descriptor initialization guarantees initialization of Parent before children.
        // main array is copied from Parent's ReturningPolicy
        if (getDescriptor().isChildDescriptor()) {
            ClassDescriptor parentDescriptor = getDescriptor().getInheritancePolicy().getParentDescriptor();
            if (parentDescriptor.hasReturningPolicy()) {
                copyMainFrom(parentDescriptor.getReturningPolicy());
            }
        }

        if (!infos.isEmpty()) {
            Hashtable<? extends DatabaseField, ? extends Info> infoHashtable = removeDuplicateAndValidateInfos(session);
            Hashtable infoHashtableUnmapped = (Hashtable)infoHashtable.clone();
            for (Enumeration<DatabaseField> fields = getDescriptor().getFields().elements();
                 fields.hasMoreElements();) {
                DatabaseField field = fields.nextElement();
                Info info = (Info)infoHashtableUnmapped.get(field);
                if (info != null) {
                    infoHashtableUnmapped.remove(field);
                    if (verifyFieldAndMapping(session, field)) {
                        if (info.getField().getType() == null) {
                            addMappedFieldToMain(field, info);
                        } else {
                            addMappedFieldToMain(info.getField(), info);
                            fieldIsNotFromDescriptor(info.getField());
                        }
                    }
                }
            }

            if (!infoHashtableUnmapped.isEmpty()) {
                Enumeration fields = infoHashtableUnmapped.keys();
                while (fields.hasMoreElements()) {
                    DatabaseField field = (DatabaseField)fields.nextElement();
                    Info info = (Info)infoHashtableUnmapped.get(field);
                    if (verifyField(session, field, getDescriptor())) {
                        if (field.getType() != null) {
                            addUnmappedFieldToMain(field, info);
                            fieldIsNotFromDescriptor(field);
                            session.log(SessionLog.FINEST, SessionLog.QUERY, "added_unmapped_field_to_returning_policy", info.toString(), getDescriptor().getJavaClassName());
                        } else {
                            if (getDescriptor().isReturnTypeRequiredForReturningPolicy()) {
                                session.getIntegrityChecker().handleError(DescriptorException.returningPolicyUnmappedFieldTypeNotSet(field.getName(), getDescriptor()));
                            }
                        }
                    }
                }
            }
        }

        initializeIsUsedToSetPrimaryKey();
    }

    protected void copyMainFrom(ReturningPolicy policy) {
        Collection<? extends DatabaseField>[][] mainToCopy = policy.main;
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            for (int state = RETURN_ONLY; state < MAIN_SIZE; state++) {
                addCollectionToMain(operation, state, mainToCopy[operation][state]);
            }
        }
    }

    /**
     * INTERNAL:
     * Both ReturningPolicies should be initialized
     */
    public boolean hasEqualMains(ReturningPolicy policy) {
        Collection[][] mainToCompare = policy.main;
        if (main == mainToCompare) {
            return true;
        }
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            for (int state = RETURN_ONLY; state < MAIN_SIZE; state++) {
                if ((main[operation][state] == null) && (mainToCompare[operation][state] != null)) {
                    return false;
                }
                if ((main[operation][state] != null) && (mainToCompare[operation][state] == null)) {
                    return false;
                }
                if (!main[operation][state].equals(mainToCompare[operation][state])) {
                    return false;
                }
            }
        }

        // now compare types
        Hashtable<DatabaseField, DatabaseField> allFields = new Hashtable<DatabaseField, DatabaseField>();
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            if (main[operation][ALL] != null) {
                Iterator<DatabaseField> it = main[operation][ALL].iterator();
                while (it.hasNext()) {
                    DatabaseField field = it.next();
                    allFields.put(field, field);
                }
            }
        }
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            if (mainToCompare[operation][ALL] != null) {
                Iterator it = mainToCompare[operation][ALL].iterator();
                while (it.hasNext()) {
                    DatabaseField fieldToCompare = (DatabaseField)it.next();
                    DatabaseField field = allFields.get(fieldToCompare);
                    if (!field.getType().equals(fieldToCompare.getType())) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * INTERNAL:
     */
    public void trimModifyRowForInsert(AbstractRecord modifyRow) {
        trimModifyRow(modifyRow, INSERT);
    }

    // operation should be either INSERT or UPDATE
    protected void trimModifyRow(AbstractRecord modifyRow, int operation) {
        if ((modifyRow == null) || modifyRow.isEmpty()) {
            return;
        }
        Collection<? extends DatabaseField> fields = main[operation][RETURN_ONLY];
        if ((fields == null) || fields.isEmpty()) {
            return;
        }
        for (int i = modifyRow.size() - 1; i >= 0; i--) {
            DatabaseField field = modifyRow.getFields().get(i);
            if (fields.contains(field)) {
                modifyRow.remove(field);
            }
        }
    }

    /**
     * PUBLIC:
     */
    public boolean isUsedToSetPrimaryKey() {
        return isUsedToSetPrimaryKey;
    }

    // only infos is filled out
    protected void clearInitialization() {
        this.main = null;
        this.tableToFieldsForGenerationMap = null;
        this.fieldsNotFromDescriptor_DefaultTable = null;
        this.fieldsNotFromDescriptor_OtherTables = null;
    }

    protected void initializeIsUsedToSetPrimaryKey() {
        this.isUsedToSetPrimaryKey = false;
        if ((main[INSERT][MAPPED] == null) || main[INSERT][MAPPED].isEmpty()) {
            return;
        }
        List<DatabaseField> primaryKeys = getDescriptor().getPrimaryKeyFields();
        for (int index = 0; (index < primaryKeys.size()) && !isUsedToSetPrimaryKey; index++) {
            this.isUsedToSetPrimaryKey = main[INSERT][MAPPED].contains(primaryKeys.get(index));
        }
    }

    protected boolean verifyFieldAndMapping(AbstractSession session, DatabaseField field) {
        boolean ok = true;
        verifyField(session, field, getDescriptor());
        DatabaseMapping mapping;
        List<DatabaseMapping> readOnlyMappings = getDescriptor().getObjectBuilder().getReadOnlyMappingsForField(field);
        if (readOnlyMappings != null) {
            for (int j = 0; j < readOnlyMappings.size(); j++) {
                mapping = readOnlyMappings.get(j);
                ok &= verifyFieldAndMapping(session, field, getDescriptor(), mapping);
            }
        }
        mapping = getDescriptor().getObjectBuilder().getMappingForField(field);
        if (mapping != null) {
            ok &= verifyFieldAndMapping(session, field, getDescriptor(), mapping);
        }
        return ok;
    }

    protected static boolean verifyFieldAndMapping(AbstractSession session, DatabaseField field, ClassDescriptor descriptor, DatabaseMapping mapping) {
        verifyField(session, field, descriptor);
        while (mapping.isAggregateObjectMapping()) {
            ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
            mapping = referenceDescriptor.getObjectBuilder().getMappingForField(field);
            verifyFieldAndMapping(session, field, referenceDescriptor, mapping);
        }
        if (!mapping.isDirectToFieldMapping() && !mapping.isTransformationMapping()) {
            String mappingTypeName = Helper.getShortClassName(mapping);
            session.getIntegrityChecker().handleError(DescriptorException.returningPolicyMappingNotSupported(field.getName(), mappingTypeName, mapping));
            return false;
        } else {
            return true;
        }
    }

    protected static boolean verifyField(AbstractSession session, DatabaseField field, ClassDescriptor descriptor) {
        boolean ok = true;
        if (field.equals(descriptor.getSequenceNumberField())) {
            ok = false;
            session.getIntegrityChecker().handleError(DescriptorException.returningPolicyFieldNotSupported(field.getName(), descriptor));
        } else if (descriptor.hasInheritance() && field.equals(descriptor.getInheritancePolicy().getClassIndicatorField())) {
            ok = false;
            session.getIntegrityChecker().handleError(DescriptorException.returningPolicyFieldNotSupported(field.getName(), descriptor));
        } else if (descriptor.usesOptimisticLocking()) {
            OptimisticLockingPolicy optimisticLockingPolicy = descriptor.getOptimisticLockingPolicy();
            if (optimisticLockingPolicy instanceof VersionLockingPolicy) {
                VersionLockingPolicy versionLockingPolicy = (VersionLockingPolicy)optimisticLockingPolicy;
                if (field.equals(versionLockingPolicy.getWriteLockField())) {
                    ok = false;
                    session.getIntegrityChecker().handleError(DescriptorException.returningPolicyFieldNotSupported(field.getName(), descriptor));
                }
            }
        }
        return ok;
    }

    /**
     * INTERNAL:
     */
    public void validationAfterDescriptorInitialization(AbstractSession session) {
        Hashtable<DatabaseField, DatabaseField> mapped = new Hashtable<DatabaseField, DatabaseField>();
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            if ((main[operation][MAPPED] != null) && !main[operation][MAPPED].isEmpty()) {
                Iterator<DatabaseField> it = main[operation][MAPPED].iterator();
                while (it.hasNext()) {
                    DatabaseField field = it.next();
                    mapped.put(field, field);
                }
            }
        }
        if (!mapped.isEmpty()) {
            for (Enumeration<DatabaseField> fields = getDescriptor().getFields().elements();
                 fields.hasMoreElements();) {
                DatabaseField fieldInDescriptor = fields.nextElement();
                DatabaseField fieldInMain = mapped.get(fieldInDescriptor);
                if (fieldInMain != null) {
                    if (fieldInMain.getType() == null) {
                        if (getDescriptor().isReturnTypeRequiredForReturningPolicy()) {
                            session.getIntegrityChecker().handleError(DescriptorException.returningPolicyMappedFieldTypeNotSet(fieldInMain.getName(), getDescriptor()));
                        }
                    } else if (isThereATypeConflict(fieldInMain, fieldInDescriptor)) {
                        session.getIntegrityChecker().handleError(DescriptorException.returningPolicyAndDescriptorFieldTypeConflict(fieldInMain.getName(), fieldInMain.getType().getName(), fieldInDescriptor.getType().getName(), getDescriptor()));
                    }
                }
            }
        }
        if (!(session.getDatasourcePlatform() instanceof DatabasePlatform)) {
            // don't attempt further diagnostics on non-relational platforms
            return;
        }
        WriteObjectQuery[] query = { getDescriptor().getQueryManager().getInsertQuery(), getDescriptor().getQueryManager().getUpdateQuery() };
        String[] queryTypeName = { "InsertObjectQuery", "UpdateObjectQuery" };
        for (int operation = INSERT; operation <= UPDATE; operation++) {
            if ((main[operation][ALL] != null) && !main[operation][ALL].isEmpty()) {
                // this operation requires some fields to be returned
                if ((query[operation] == null) || (query[operation].getDatasourceCall() == null)) {
                    if (!session.getPlatform().canBuildCallWithReturning()) {
                        session.getIntegrityChecker().handleError(DescriptorException.noCustomQueryForReturningPolicy(queryTypeName[operation], Helper.getShortClassName(session.getPlatform()), getDescriptor()));
                    }
                } else if (query[operation].getDatasourceCall() instanceof StoredProcedureCall) {
                    // SQLCall with custom SQL calculates its outputRowFields later (in prepare() method) -
                    // that's why SQLCall can't be verified here.
                    DatabaseCall customCall = (DatabaseCall)query[operation].getDatasourceCall();
                    Enumeration outputRowFields = customCall.getOutputRowFields().elements();
                    Collection<DatabaseField> notFoundInOutputRow = createCollection();
                    notFoundInOutputRow.addAll(main[operation][ALL]);
                    while (outputRowFields.hasMoreElements()) {
                        notFoundInOutputRow.remove(outputRowFields.nextElement());
                    }
                    if (!notFoundInOutputRow.isEmpty()) {
                        Iterator<DatabaseField> it = notFoundInOutputRow.iterator();
                        while (it.hasNext()) {
                            DatabaseField field = it.next();
                            session.getIntegrityChecker().handleError(DescriptorException.customQueryAndReturningPolicyFieldConflict(field.getName(), queryTypeName[operation], getDescriptor()));
                        }
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Returns an equal field held by ReturningPolicy, or null.
     */
    public DatabaseField getField(DatabaseField field) {
        DatabaseField foundField = null;
        if (this.fieldsNotFromDescriptor_DefaultTable != null) {
            foundField = this.fieldsNotFromDescriptor_DefaultTable.get(field);
        }
        if ((foundField == null) && (this.fieldsNotFromDescriptor_OtherTables != null)) {
            foundField = this.fieldsNotFromDescriptor_OtherTables.get(field);
        }
        return foundField;
    }
}
