/*******************************************************************************
 * Copyright (c) 1998, 2013 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 v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 *     07/13/2012-2.5 Guy Pelletier 
 *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
 *     08/24/2012-2.5 Guy Pelletier 
 *       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
 ******************************************************************************/  
package org.eclipse.persistence.internal.queries;

import java.util.*;
import java.io.*;

import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.descriptors.VersionLockingPolicy;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventManager;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.tools.profiler.QueryMonitor;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.descriptors.ClassDescriptor;

/**
 * <p><b>Purpose</b>:
 * Abstract class for all database query mechanism objects.
 * DatabaseQueryMechanism is actually a helper class and currently is required
 * for all types of queries.  Most of the work performed by the query framework is
 * performed in the query mechanism.  The query mechanism contains the internal
 * knowledge necessary to perform the specific database operation.
 * <p>
 * <p><b>Responsibilities</b>:
 * Provide a common protocol for query mechanism objects.
 * Provides all of the database specific work for the assigned query.
 *
 * @author Yvon Lavoie
 * @since TOPLink/Java 1.0
 */
public abstract class DatabaseQueryMechanism implements Cloneable, Serializable {

    /** The database query that uses this mechanism. */
    protected DatabaseQuery query;

    /**
     * Initialize the state of the query.
     */
    public DatabaseQueryMechanism() {
    }

    /**
     * Initialize the state of the query
     * @param query - owner of mechanism
     */
    public DatabaseQueryMechanism(DatabaseQuery query) {
        this.query = query;
    }

    /**
     * Add the initial write lock value to the row for insert.
     */
    protected void addWriteLockFieldForInsert() {
        if (getDescriptor().usesOptimisticLocking()) {
            getDescriptor().getOptimisticLockingPolicy().setupWriteFieldsForInsert(getWriteObjectQuery());
        }
    }

    /**
     * Internal:
     * In the case of EJBQL, an expression needs to be generated. Build the required expression.
     */
    public void buildSelectionCriteria(AbstractSession session) {
        // Default is do nothing
    }

    /**
     * Perform a cache lookup for the query. If the translation row contains 
     * all the parameters (which are part of the primary key) from the prepared 
     * call, then a cache check will be performed.
     * 
     * If the object is found in the cache, return it; otherwise return null.
     */
    public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
        // Null check added for CR#4295 - TW
        if ((translationRow == null) || (translationRow.isEmpty())) {
            return null;
        }
        
        // Bug 5529564
        // The query wasn't prepared most likely because arguments were 
        // provided. Use them for the cache lookup.
        List queryFields;
        if (query.getCall() == null) {
            // TODO: This is a bug, arguments is a list of Strings, not fields.
            // Also if the call was null, it would be an expression, if it was not
            // prepared the parameters would be empty.
            queryFields = query.getArguments();
        } else {
            // The query was prepared. Use the parameters of the call to look
            // up the object in cache.
            queryFields = query.getCall().getParameters();
        }
        
        ClassDescriptor descriptor = getDescriptor();
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();
        
        // Check that the query is by primary key.
        for (DatabaseField primaryKeyField : primaryKeyFields) {
            if (!queryFields.contains(primaryKeyField)) {
                return null;
            }
        }
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(translationRow, session);
        if (primaryKey == null) {
            return null;
        }
        
        if (query.isObjectBuildingQuery() && ((ObjectBuildingQuery)query).requiresDeferredLocks() || descriptor.shouldAcquireCascadedLocks()) {
            return session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(primaryKey, getReadObjectQuery().getReferenceClass(), false, descriptor);
        } else {
            return session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(primaryKey, getReadObjectQuery().getReferenceClass(), false, descriptor);
        }        
    }

    /**
     * Clone the mechanism
     */
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }

    /**
     * Clone the mechanism for the specified query clone.
     */
    public DatabaseQueryMechanism clone(DatabaseQuery queryClone) {
        DatabaseQueryMechanism clone = (DatabaseQueryMechanism)clone();
        clone.setQuery(queryClone);
        return clone;
    }

    /**
     * Read all rows from the database using a cursored stream.
     * @exception  DatabaseException - an error has occurred on the database
     */
    public abstract DatabaseCall cursorSelectAllRows() throws DatabaseException;

    /**
     * Delete a collection of objects
     * This should be overridden by subclasses.
     * @exception  DatabaseException - an error has occurred on the database
     */
    public boolean isJPQLCallQueryMechanism() {
        return false;
    }

    public abstract Integer deleteAll() throws DatabaseException;

    /**
     * Delete an object
     * This should be overridden by subclasses.
     * @exception DatabaseException
     * @return the row count.
     */
    public abstract Integer deleteObject() throws DatabaseException;

    /**
     * Execute a execute SQL call. 
     * This should be overridden by subclasses.
     * @exception DatabaseException
     * @return true if the first result is a result set and false if it is an 
     *   update count or there are no results other than through INOUT and OUT
     *   parameterts, if any.
     */
    public abstract Object execute() throws DatabaseException;

    /**
     * Execute a non selecting SQL call
     * This should be overridden by subclasses.
     * @exception DatabaseException
     * @return the row count.
     */
    public abstract Integer executeNoSelect() throws DatabaseException;

    /**
     * Execute a select SQL call and return the rows.
     * This should be overriden by subclasses.
     * @exception DatabaseException
     */
    public abstract Vector executeSelect() throws DatabaseException;

    /**
     * Check whether the object already exists on the database; then
     * perform an insert or update, as appropriate.
     * This write is used for non-unit of work (old-commit) operations.
     * Return the object being written.
     */
    public Object executeWrite() throws DatabaseException, OptimisticLockException {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        CommitManager commitManager = getSession().getCommitManager();

        // if the object has already been committed, no work is required
        if (commitManager.isCommitCompletedInPostOrIgnore(object)) {
            return object;
        }

        // check whether the object is already being committed -
        // if it is and it is new, then a shallow insert must be done
        if (commitManager.isCommitInPreModify(object)) {
            shallowInsertObjectForWrite(object, writeQuery, commitManager);
            return object;
        }

        try {
            getSession().beginTransaction();

            if (writeQuery.getObjectChangeSet() == null) {
                // PERF: Avoid events if no listeners.
                if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                    // only throw the events if there is no changeset otherwise the event will be thrown twice
                    // once by the calculate changes code and here
                    getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreWriteEvent, writeQuery));
                }
            }
            writeQuery.executeCommit();

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
            }

            getSession().commitTransaction();

            // notify the commit manager of the completion to the commit
            commitManager.markCommitCompleted(object);

            return object;

        } catch (RuntimeException exception) {
            getSession().rollbackTransaction();
            commitManager.markCommitCompleted(object);
            throw exception;
        }
    }

    /**
     * Execute the call that was deferred to the commit manager.
     * This is used to allow multiple table batching and deadlock avoidance.
     */
    public void executeDeferredCall(DatasourceCall call) {
        // Do nothing by default.
    }
    
    /**
     * Check whether the object already exists on the cadatabase; then
     * perform an insert or update, as appropriate.
     * This method was moved here, from WriteObjectQuery.execute(),
     * so we can hide the source.
     * Return the object being written.
     */
    public Object executeWriteWithChangeSet() throws DatabaseException, OptimisticLockException {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
        ClassDescriptor descriptor = getDescriptor();
        AbstractSession session = getSession();
        CommitManager commitManager = session.getCommitManager();
        Object object = writeQuery.getObject();
        // If there are no changes then there is no work required
        // Check for forcedUpdate Version and Optimistic read lock (hasForcedChanges() set in ObjectChangePolicy)
        if (!objectChangeSet.hasChanges() && !objectChangeSet.hasForcedChanges()) {
            commitManager.markCommitCompleted(object);
            return object;
        }
        // If the object has already been committed, no work is required
        // need to check for the object to ensure insert wasn't completed already.
        if (commitManager.isCommitCompletedInPostOrIgnore(object)) {
            return object;
        }
        try {
            writeQuery.executeCommitWithChangeSet();

            // PERF: Avoid events if no listeners.
            if (descriptor.getEventManager().hasAnyEventListeners()) {
                descriptor.getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
            }

            // Notify the commit manager of the completion to the commit.
            commitManager.markCommitCompleted(object);

            return object;

        } catch (RuntimeException exception) {
            commitManager.markCommitCompleted(object);
            throw exception;
        }
    }

    /**
     * Convenience method
     */
    protected ClassDescriptor getDescriptor() {
        return this.query.getDescriptor();
    }

    /**
     * Convenience method
     */
    public AbstractRecord getModifyRow() {
        if (this.query.isModifyQuery()) {
            return ((ModifyQuery)this.query).getModifyRow();
        } else {
            return null;
        }
    }

    /**
     * Return the query that uses the mechanism.
     */
    public DatabaseQuery getQuery() {
        return query;
    }

    /**
     * Convenience method
     */
    protected ReadObjectQuery getReadObjectQuery() {
        return (ReadObjectQuery)this.query;
    }

    /**
     * Return the selection criteria for the mechanism.
     * By default this is null. This method exists because both statement and expression
     * mechanisms use an expression and some code in the mappings depends on returning this.
     */
    public Expression getSelectionCriteria() {
        return null;
    }

    /**
     * Convenience method
     */
    protected AbstractSession getSession() {
        return this.query.getSession();
    }

    /**
     * Convenience method
     */
    protected AbstractSession getExecutionSession() {
        return this.query.getExecutionSession();
    }

    /**
     * Convenience method
     */
    protected AbstractRecord getTranslationRow() {
        return this.query.getTranslationRow();
    }

    /**
     * Convenience method
     */
    protected WriteObjectQuery getWriteObjectQuery() {
        return (WriteObjectQuery)this.query;
    }

    /**
     * Insert an object.
     */
    public abstract void insertObject() throws DatabaseException;

    /**
     *  Insert an object and provide the opportunity to reprepare prior to the insert.
     *  This will be overridden
     *  CR#3237
     */
    public void insertObject(boolean reprepare) {
        insertObject();
    }

    /**
     * Insert an object in the database.
     * This is used for both uow and non-uow (old-commit and change-set) operations.
     */
    public void insertObjectForWrite() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ClassDescriptor descriptor = getDescriptor();
        DescriptorQueryManager queryManager = descriptor.getQueryManager();
        boolean isFKUpdate = false; // Bug 319276
        
        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 && queryManager.hasInsertQuery()// there is a user-defined query
                 && isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedInsert();
            return;
        }
        Object object = writeQuery.getObject();
        AbstractSession session = writeQuery.getSession();
        ObjectChangeSet changeSet = writeQuery.getObjectChangeSet();
        CommitManager commitManager = session.getCommitManager();
        DescriptorEventManager eventManager = descriptor.getEventManager();

        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);

        if (changeSet == null) {
            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreInsertEvent, writeQuery));
            }
        }

        // check whether deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preInsert(writeQuery);
        }

        // In a unit of work/writeObjects the preInsert may have caused a shallow insert of this object,
        // in this case this second write must do an update.
        if (commitManager.isShallowCommitted(object)) {
            isFKUpdate = true; // Bug 319276
            updateForeignKeyFieldAfterInsert();
        } else {
            AbstractRecord modifyRow = writeQuery.getModifyRow();
            if (modifyRow == null) {// Maybe have been passed in as in aggregate collection.
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, session, WriteType.INSERT));
                } else {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForShallowInsert(object, session));
                }
            } else {
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(modifyRow, object, session, WriteType.INSERT));
                } else {
                    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForShallowInsert(modifyRow, object, session));
                }
            }
            modifyRow = getModifyRow();
            // the modify row and the translation row are the same for insert
            writeQuery.setTranslationRow(modifyRow);
            if (!descriptor.isAggregateCollectionDescriptor()) {// Should/cannot be recomputed in aggregate collection.
                writeQuery.setPrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session));
            }
            addWriteLockFieldForInsert();
            if (descriptor.hasSerializedObjectPolicy()) {
                descriptor.getSerializedObjectPolicy().putObjectIntoRow(modifyRow, object, session);
            }

            // CR#3237
            // Store the size of the modify row so we can determine if the user has added to the row in the insert.
            int modifyRowSize = modifyRow.size();

            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToInsertEvent, writeQuery);
                event.setRecord(modifyRow);
                eventManager.executeEvent(event);
            }

            if (QueryMonitor.shouldMonitor()) {
                QueryMonitor.incrementInsert(writeQuery);
            }
            // CR#3237
            // Call insert with a boolean that tells it to reprepare if the user has altered the modify row.
            insertObject(modifyRowSize != modifyRow.size());

            // register the object before post insert to resolve possible cycles
            registerObjectInIdentityMap(object, descriptor, session);
        }

        commitManager.markPostModifyCommitInProgress(object);
        // Verify if deep shallow modify is turned on.
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postInsert(writeQuery);
        }
        
        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            if (isFKUpdate) { // Bug 319276
                descriptor.getHistoryPolicy().postUpdate(writeQuery, true);
            }
            else {
                descriptor.getHistoryPolicy().postInsert(writeQuery);
            }
        }

        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostInsertEvent, writeQuery));
        }
    }

    /**
     * Return true if this is a call query mechanism
     */
    public boolean isCallQueryMechanism() {
        return false;
    }

    /**
     * Return true if this is an expression query mechanism
     */
    public boolean isExpressionQueryMechanism() {
        return false;
    }

    /**
     * Return true if this is a query by example mechanism
     */
    public boolean isQueryByExampleMechanism() {
        return false;
    }

    /**
     * Return true if this is a statement query mechanism
     */
    public boolean isStatementQueryMechanism() {
        return false;
    }

    /**
     * Insert the object using the user defined query.
     * This ensures that the query is cloned and prepared correctly.
     */
    protected void performUserDefinedInsert() {
        performUserDefinedWrite(getDescriptor().getQueryManager().getInsertQuery());
    }

    /**
     * Update the object using the user defined query.
     * This ensures that the query is cloned and prepared correctly.
     */
    protected void performUserDefinedUpdate() {
        performUserDefinedWrite(getDescriptor().getQueryManager().getUpdateQuery());
    }

    /**
     * Write the object using the specified user-defined query.
     * This ensures that the query is cloned and prepared correctly.
     */
    protected void performUserDefinedWrite(WriteObjectQuery userDefinedWriteQuery) {
        WriteObjectQuery query = getWriteObjectQuery();
        userDefinedWriteQuery.checkPrepare(query.getSession(), query.getTranslationRow());

        WriteObjectQuery writeQuery = (WriteObjectQuery)userDefinedWriteQuery.clone();
        writeQuery.setIsExecutionClone(true);
        writeQuery.setObject(query.getObject());
        writeQuery.setObjectChangeSet(query.getObjectChangeSet());
        writeQuery.setCascadePolicy(query.getCascadePolicy());
        writeQuery.setShouldMaintainCache(query.shouldMaintainCache());
        writeQuery.setTranslationRow(query.getTranslationRow());
        writeQuery.setModifyRow(query.getModifyRow());
        writeQuery.setPrimaryKey(query.getPrimaryKey());
        writeQuery.setSession(query.getSession());

        // If there is a changeset, the change set method must be used.
        if (writeQuery.getObjectChangeSet() != null) {
            writeQuery.executeCommitWithChangeSet();
        } else {
            writeQuery.executeCommit();
        }
    }

    /**
     * This is different from 'prepareForExecution()'
     * in that this is called on the original query,
     * and the other is called on the clone of the query.
     * This query is copied for concurrency so this prepare can only setup things that
     * will apply to any future execution of this query.
     */
    public void prepare() throws QueryException {
        // the default is to do nothing
    }

    /**
     * Pre-pare for a cursored execute.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareCursorSelectAllRows() throws QueryException;

    /**
     * Prepare for a delete all.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareDeleteAll() throws QueryException;

    /**
     * Prepare for a delete.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareDeleteObject() throws QueryException;

    /**
     * Pre-pare for a select execute.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareDoesExist(DatabaseField field) throws QueryException;

    /**
     * Prepare for a raw (non-object), non-selecting call.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareExecuteNoSelect() throws QueryException;

    /**
     * Prepare for a raw execute call.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareExecute() throws QueryException;
    
    /**
     * Prepare for a raw (non-object) select call.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareExecuteSelect() throws QueryException;

    /**
     * Prepare for an insert.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareInsertObject() throws QueryException;

    /**
     * Pre-pare for a select execute.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareReportQuerySelectAllRows() throws QueryException;

    /**
     * Pre-pare a report query for a sub-select.
     */
    public abstract void prepareReportQuerySubSelect() throws QueryException;

    /**
     * Prepare for a select returning (possibly) multiple rows.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareSelectAllRows() throws QueryException;

    /**
     * Prepare for a select returning a single row.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareSelectOneRow() throws QueryException;

    /**
     * Prepare for an update.
     * This is sent to the original query before cloning.
     */
    public abstract void prepareUpdateObject() throws QueryException;

    /**
       * Prepare for an update all.
       * This is sent to the original query before cloning.
       */
    public abstract void prepareUpdateAll() throws QueryException;

    /**
     * Store the query object in the identity map.
     */
    protected void registerObjectInIdentityMap(Object object, ClassDescriptor descriptor, AbstractSession session) {
        WriteObjectQuery query = getWriteObjectQuery();
        if (query.shouldMaintainCache()) {
            if (descriptor.usesOptimisticLocking()) {
                Object optimisticLockValue = descriptor.getOptimisticLockingPolicy().getValueToPutInCache(query.getModifyRow(), session);
                session.getIdentityMapAccessorInstance().putInIdentityMap(object, query.getPrimaryKey(), optimisticLockValue, System.currentTimeMillis(), descriptor);
            } else {
                session.getIdentityMapAccessorInstance().putInIdentityMap(object, query.getPrimaryKey(), null, System.currentTimeMillis(), descriptor);
            }
        }
    }

    /**
     * INTERNAL:
     * Read all rows from the database.
     */
    public abstract Vector selectAllReportQueryRows() throws DatabaseException;

    /**
     * Read and return rows from the database.
     */
    public abstract Vector selectAllRows() throws DatabaseException;

    /**
     * Read and return a row from the database.
     */
    public abstract AbstractRecord selectOneRow() throws DatabaseException;

    /**
     * Read and return a row from the database for an existence check.
     */
    public abstract AbstractRecord selectRowForDoesExist(DatabaseField field) throws DatabaseException;
    
    /**
     * Set the query that uses this mechanism.
     */
    public void setQuery(DatabaseQuery query) {
        this.query = query;
    }

    /**
     * Shallow insert the specified object, if necessary.
     */
    protected void shallowInsertObjectForWrite(Object object, WriteObjectQuery writeQuery, CommitManager commitManager) throws DatabaseException, OptimisticLockException {
        boolean doesExist;

        if (getSession().isUnitOfWork()) {
            UnitOfWorkImpl uow = (UnitOfWorkImpl)getSession();
            doesExist = !uow.isCloneNewObject(object);
            if (doesExist) {
                doesExist = uow.isObjectRegistered(object);
            }
        } else {
            // clone and initialize the does exist query
            DoesExistQuery existQuery = (DoesExistQuery)getDescriptor().getQueryManager().getDoesExistQuery().clone();
            existQuery.setObject(object);
            existQuery.setPrimaryKey(writeQuery.getPrimaryKey());
            existQuery.setDescriptor(getDescriptor());
            existQuery.setTranslationRow(getTranslationRow());

            doesExist = ((Boolean)getSession().executeQuery(existQuery)).booleanValue();
        }

        if (!doesExist) {
            // a shallow insert must be performed
            writeQuery.dontCascadeParts();
            insertObjectForWrite();
            // mark this object as shallow committed so that the insert will do an update
            commitManager.markShallowCommit(object);
        }
    }

    /**
     * Update the foreign key fields when resolving a bi-directonal reference in a UOW.
     * This must always be dynamic as it is called within an insert query and is really part of the insert
     * and does not fire update events or worry about locking.
     */
    protected void updateForeignKeyFieldAfterInsert() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();

        writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
        // reset the translation row because the insert has occurred and the id has
        // been assigned to the object, but not the row
        writeQuery.setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(object, getSession()));

        updateForeignKeyFieldAfterInsert(writeQuery);
    }

    /**
       * Issue update SQL statement
       */
    public abstract Integer updateAll() throws DatabaseException;

    /**
     * Update an object.
     * Return the row count.
     */
    public abstract Integer updateObject() throws DatabaseException;

    /**
     * Update the foreign key fields when resolving a bi-directonal reference in a UOW.
     * This must always be dynamic as it is called within an insert query and is really part of the insert
     * and does not fire update events or worry about locking.
     */
    protected abstract void updateForeignKeyFieldAfterInsert(WriteObjectQuery writeQuery);

    /**
     * Update the foreign key fields to null when resolving a deletion cycle.
     * This must always be dynamic as it is called within an delete query and is really part of the delete
     * and does not fire update events or worry about locking.
     */
    public void updateForeignKeyFieldBeforeDelete() {
        // Nothing by default.
    }
    
    protected void updateObjectAndRowWithReturnRow(Collection returnFields, boolean isFirstCallForInsert) {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        AbstractRecord outputRow = (AbstractRecord)writeQuery.getProperties().get("output");
        if ((outputRow == null) || outputRow.isEmpty()) {
            return;
        }
        AbstractRecord row = new DatabaseRecord();
        for (Iterator iterator = returnFields.iterator(); iterator.hasNext();) {
            DatabaseField field = (DatabaseField)iterator.next();
            if (outputRow.containsKey(field)) {
                row.put(field, outputRow.get(field));
            }
        }
        if (row.isEmpty()) {
            return;
        }

        Object object = writeQuery.getObject();

        ObjectChangeSet objectChangeSet = null;
        if (getSession().isUnitOfWork()) {
            objectChangeSet = writeQuery.getObjectChangeSet();
            if ((objectChangeSet == null) && (((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet() != null)) {
                objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
            }
        }
        getDescriptor().getObjectBuilder().assignReturnRow(object, writeQuery.getSession(), row, objectChangeSet);

        Object primaryKey = null;
        if (isFirstCallForInsert) {
            AbstractRecord pkToModify = new DatabaseRecord();
            List primaryKeyFields = getDescriptor().getPrimaryKeyFields();
            for (int i = 0; i < primaryKeyFields.size(); i++) {
                DatabaseField field = (DatabaseField)primaryKeyFields.get(i);
                if (row.containsKey(field)) {
                    pkToModify.put(field, row.get(field));
                }
            }
            if (!pkToModify.isEmpty()) {
                primaryKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession());
                writeQuery.setPrimaryKey(primaryKey);
                // Now I need to update the row
                getModifyRow().putAll(pkToModify);
                getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow(), object, getSession());
            }
        }

        if (objectChangeSet != null) {
            if (primaryKey != null) {
                objectChangeSet.setId(primaryKey);
            }
        }
    }

    /**
     * Update the object's primary key by fetching a new sequence number from the accessor.
     */
    protected void updateObjectAndRowWithSequenceNumber() throws DatabaseException {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        writeQuery.getDescriptor().getObjectBuilder().assignSequenceNumber(writeQuery);
    }

    /**
     * Update the object.
     * This is only used for non-unit-of-work updates.
     */
    public void updateObjectForWrite() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ClassDescriptor descriptor = getDescriptor();
        DescriptorQueryManager queryManager = descriptor.getQueryManager();
        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 && queryManager.hasUpdateQuery()// there is a user-defined query
                 && isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedUpdate();
            return;
        }
        Object object = writeQuery.getObject();
        AbstractSession session = getSession();
        CommitManager commitManager = session.getCommitManager();
        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);
        DescriptorEventManager eventManager = descriptor.getEventManager();
        if (writeQuery.getObjectChangeSet() == null) {
            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreUpdateEvent, writeQuery));
            }
        }

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preUpdate(writeQuery);
        }

        // The row must not be built until after preUpdate in case the object reference has changed.
        // For a user defined update in the uow to row must be built twice to check if any update is required.
        if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && (!getSession().isUnitOfWork())) {
            writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, getSession(), WriteType.UNDEFINED));
        } else {
            writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForUpdate(writeQuery));
        }

        // Optimistic read lock implementation
        Boolean shouldModifyVersionField = null;
        if (session.isUnitOfWork() && ((UnitOfWorkImpl)session).hasOptimisticReadLockObjects()) {
            shouldModifyVersionField = (Boolean)((UnitOfWorkImpl)session).getOptimisticReadLockObjects().get(writeQuery.getObject());
        }

        if (!getModifyRow().isEmpty() || (shouldModifyVersionField != null) || ((descriptor.getCMPPolicy() != null) && (descriptor.getCMPPolicy().getForceUpdate()))) {
            // If user defined the entire row is required. Must not be built until change is known.
            if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && getSession().isUnitOfWork()) {
                writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, getSession(), WriteType.UNDEFINED));
            }

            // Update the write lock field if required.
            if (descriptor.usesOptimisticLocking()) {
                OptimisticLockingPolicy policy = descriptor.getOptimisticLockingPolicy();
                policy.addLockValuesToTranslationRow(writeQuery);

                if (!getModifyRow().isEmpty() || shouldModifyVersionField.booleanValue()) {
                    // Update the row with newer lock value.
                    policy.updateRowAndObjectForUpdate(writeQuery, object);
                } else if (!shouldModifyVersionField.booleanValue() && (policy instanceof VersionLockingPolicy)) {
                    // Add the existing write lock value to the for a "read" lock (requires something to update).
                    ((VersionLockingPolicy)policy).writeLockValueIntoRow(writeQuery, object);
                }
            }
            if (descriptor.hasSerializedObjectPolicy()) {
                descriptor.getSerializedObjectPolicy().putObjectIntoRow(getModifyRow(), object, session);
            }

            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
                event.setRecord(getModifyRow());
                eventManager.executeEvent(event);
            }

            if (QueryMonitor.shouldMonitor()) {
                QueryMonitor.incrementUpdate(getWriteObjectQuery());
            }
            int rowCount = updateObject().intValue();

            if (rowCount < 1) {
                if (session.hasEventManager()) {
                    session.getEventManager().noRowsModified(writeQuery, object);
                }
            }
            if (descriptor.usesOptimisticLocking()) {
                descriptor.getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
            }
        }

        commitManager.markPostModifyCommitInProgress(object);

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postUpdate(writeQuery);
        }
        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            descriptor.getHistoryPolicy().postUpdate(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
        }
    }

    /**
     * Update the object.
     * This is used by the unit-of-work update.
     */
    public void updateObjectForWriteWithChangeSet() {
        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ObjectChangeSet changeSet = writeQuery.getObjectChangeSet();
        Object object = writeQuery.getObject();
        ClassDescriptor descriptor = getDescriptor();
        DescriptorQueryManager queryManager = descriptor.getQueryManager();
        AbstractSession session = getSession();
        CommitManager commitManager = session.getCommitManager();
        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 && queryManager.hasUpdateQuery()// there is a user-defined query
                 && isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            // This must be done here because the user defined update does not use a changeset so it will not be set otherwise
            commitManager.markPreModifyCommitInProgress(object);
            performUserDefinedUpdate();
            return;
        }
        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);
        DescriptorEventManager eventManager = descriptor.getEventManager();

        if (changeSet.hasChanges()) {
            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.PreUpdateWithChangesEvent, writeQuery);
                eventManager.executeEvent(event);

                // PreUpdateWithChangesEvent listeners may have altered the object - should recalculate the change set.
                UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)session).getUnitOfWorkChangeSet();
                if (!uowChangeSet.isChangeSetFromOutsideUOW() && writeQuery.getObjectChangeSet().shouldRecalculateAfterUpdateEvent()){
                    // writeQuery.getObjectChangeSet() is mapped to object in uowChangeSet.
                    // It is first cleared then re-populated by calculateChanges method.
                    if (!descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy() ){
                        // clear the change set without clearing the maps keys since they are not alterable by the event
                        // if the map is changed, it will be changed in the owning object and the
                        // change set will be changed there as well.
                        writeQuery.getObjectChangeSet().clear(false);
                    }
                    if (descriptor.getObjectChangePolicy().calculateChangesForExistingObject(object, uowChangeSet, ((UnitOfWorkImpl)session), descriptor, false) == null) {
                        // calculateChanges returns null in case the changeSet doesn't have changes.
                        // It should be removed from the list of ObjectChangeSets that have changes in uowChangeSet.
                        uowChangeSet.getAllChangeSets().remove(writeQuery.getObjectChangeSet());
                    }
                }
            }
        }
         
        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preUpdate(writeQuery);
        }

        // The row must not be built until after preUpdate in case the object reference has changed.
        // For a user defined update in the uow to row must be built twice to check if any update is required.
        writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForUpdateWithChangeSet(writeQuery));
            
        Boolean shouldModifyVersionField = changeSet.shouldModifyVersionField();
        if (!getModifyRow().isEmpty() || shouldModifyVersionField != null || changeSet.hasCmpPolicyForcedUpdate()) {
            // If user defined the entire row is required. Must not be built until change is known.
            if (writeQuery.isUserDefined() || writeQuery.isCallQuery()) {
                writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, session, WriteType.UNDEFINED));
            }
            OptimisticLockingPolicy lockingPolicy = descriptor.getOptimisticLockingPolicy();

            // Update the write lock field if required.
            if (lockingPolicy != null) {
                lockingPolicy.addLockValuesToTranslationRow(writeQuery);
                // Do not lock an object that has previously been optimistically locked within the RWUoW
                boolean existingOptimisticLock = false;
                if (session instanceof RepeatableWriteUnitOfWork) {
                    RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork)session;
                    if (uow.getOptimisticReadLockObjects().get(object) != null && uow.getCumulativeUOWChangeSet() != null 
                            && uow.getCumulativeUOWChangeSet().getObjectChangeSetForClone(object) != null) {
                        existingOptimisticLock = true;
                    }
                }
                if (!existingOptimisticLock) {
                    // update the row and object if shouldModifyVersionField is non null and has a value of true (a forced update),
                    // or if there is no forced update and modifyRow has modifications
                    if ((shouldModifyVersionField != null && shouldModifyVersionField) || !getModifyRow().isEmpty()) {
                        // Update the row with newer lock value.
                        lockingPolicy.updateRowAndObjectForUpdate(writeQuery, object);
                    } else if (!shouldModifyVersionField && (lockingPolicy instanceof VersionLockingPolicy)) {
                        // Add the existing write lock value to the for a "read" lock (requires something to update).
                        ((VersionLockingPolicy)lockingPolicy).writeLockValueIntoRow(writeQuery, object);
                    }
                }
            }
            
            if (descriptor.hasSerializedObjectPolicy()) {
                descriptor.getSerializedObjectPolicy().putObjectIntoRow(getModifyRow(), object, session);
            }

            // PERF: Avoid events if no listeners.
            if (eventManager.hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
                event.setRecord(getModifyRow());
                eventManager.executeEvent(event);
            }

            if (QueryMonitor.shouldMonitor()) {
                QueryMonitor.incrementUpdate(getWriteObjectQuery());
            }
            int rowCount = updateObject().intValue();

            if (rowCount < 1) {
                if (session.hasEventManager()) {
                    session.getEventManager().noRowsModified(writeQuery, object);
                }
            }
            if (lockingPolicy != null) {
                lockingPolicy.validateUpdate(rowCount, object, writeQuery);
            }
        }

        commitManager.markPostModifyCommitInProgress(object);

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postUpdate(writeQuery);
        }
        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            descriptor.getHistoryPolicy().postUpdate(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
        }
    }
    
    /**
     * Unprepare the call if required.
     */
    public void unprepare() {
        
    }
}
