/*
 * 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<? extends DatabaseField> getFieldsToGenerateInsert(DatabaseTable table) {
        return getVectorOfFieldsToGenerate(INSERT, table);
    }

    /**
     * INTERNAL:
     */
    public List<? extends 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;
    }
}
