private void ModifyRecordContent(
            OAdEntity entity,
            IMigrationAction action,
            ConversionResult convRslt,
            List <string> skipFields)
        {
            XmlNodeList columns = action.MigrationActionDescription.SelectNodes("/WorkItemChanges/Columns/Column");

            if (null == columns)
            {
                throw new MigrationException(ClearQuestResource.ClearQuest_Error_InvalidActionDescription, action.ActionId);
            }

            // get the record's display name for updating conversion history
            string recordDisplayName = CQWrapper.GetEntityDisplayName(entity);

            // *********
            // cache the current history count for all "history fields"
            // i.e. pairs of HistoryFieldName, count
            Dictionary <string, int> recordHistoryCountCache = new Dictionary <string, int>();

            BuildRecordHistoryCountCache(entity, recordHistoryCountCache);

            SetRecordEditable(entity);

            StringBuilder updateLog = new StringBuilder();

            PrintUpdateLogHeader(action, updateLog);

            string entityDefName = CQWrapper.GetEntityDefName(entity);
            string stateTransitionFieldDefName = m_migrationContext.GetStateField(entityDefName);

            string retVal;
            bool   recordIsUpdated = false;

            foreach (XmlNode columnData in columns)
            {
                string stringVal = columnData.FirstChild.InnerText;
                string fieldName = columnData.Attributes["ReferenceName"].Value;
                Debug.Assert(!string.IsNullOrEmpty(fieldName),
                             "Field ReferenceName is absent in the Migration Description");

                if (CQStringComparer.FieldName.Equals(fieldName, stateTransitionFieldDefName) ||
                    (null != skipFields && skipFields.Contains(fieldName, CQStringComparer.FieldName)))
                {
                    // skip or "State" field, as it has already been submitted in a separate history/revision
                    continue;
                }

                bool         setFieldValue     = false;
                OAdFieldInfo aFieldInfo        = CQWrapper.GetEntityFieldValue(entity, fieldName);
                int          fieldRequiredness = CQWrapper.GetRequiredness(aFieldInfo);
                switch (fieldRequiredness)
                {
                case CQConstants.MANDATORY:
                case CQConstants.OPTIONAL:
                    setFieldValue = true;
                    break;

                case CQConstants.READONLY:
                    // [teyang] TODO conflict handling
                    TraceManager.TraceWarning("Field {0} is READONLY", fieldName);
                    setFieldValue = false;
                    break;

                case CQConstants.USEHOOK:
                    // [teyang] TODO conflict handling
                    TraceManager.TraceWarning("Field {0} is USEHOOK", fieldName);
                    setFieldValue = false;
                    break;

                default:
                    throw new InvalidOperationException();
                }

                if (setFieldValue)
                {
                    int attempt1Count = 0;
                    if (!SetFieldValue(action, entity, fieldName, stringVal, ref attempt1Count))
                    {
                        return;
                    }
                    AddFieldToUpdateLog(fieldName, stringVal, updateLog);
                    recordIsUpdated = true;
                }
            }

            if (!recordIsUpdated)
            {
                // no update has been made to the record, mark this action to be skipped
                CQWrapper.Revert(entity);
                if (action.State == ActionState.Pending)
                {
                    action.State = ActionState.Skipped;
                }

                return;
            }

            AddLineToUpdateLog(updateLog);
            int attempt2Count = 0;

            if (!SetFieldValue(action, entity, NoteEntryFieldName, updateLog.ToString(), ref attempt2Count))
            {
                return;
            }

            retVal = CQWrapper.Validate(entity);
            if (!string.IsNullOrEmpty(retVal))
            {
                IEnumerable <Microsoft.TeamFoundation.Migration.ClearQuestAdapter.CQTextParser.RecordValidationResult> validationResults;
                if (CQTextParser.RecordValidationTextParser.TryParse(retVal, out validationResults))
                {
                    foreach (CQTextParser.RecordValidationResult rslt in validationResults)
                    {
                        MigrationConflict      conflict = ClearQuestInvalidFieldValueConflictType.CreateConflict(rslt, action);
                        List <MigrationAction> actions;
                        var resolutionRslt = m_conflictManagerService.TryResolveNewConflict(m_conflictManagerService.SourceId, conflict, out actions);
                        if (!resolutionRslt.Resolved)
                        {
                            action.ChangeGroup.ContainsBackloggedAction = true;
                            return;
                        }
                    }
                }
                else
                {
                    throw new InvalidOperationException(retVal);
                }
            }

            retVal = CQWrapper.Commmit(entity);
            if (!string.IsNullOrEmpty(retVal))
            {
                // [teyang] TODO: invalid update conflict handling
                throw new InvalidOperationException(retVal);
            }

            if (action.State == ActionState.Pending)
            {
                action.State = ActionState.Complete;
            }

            // *********
            // now comparing to the cache, so that we can clearly identify the item:version pairs
            // e.g. TargetCQRecordDisplayName : HistoryFieldName::LatestHistoryIndex
            Dictionary <string, int[]> updatedHistoryIndices = new Dictionary <string, int[]>();

            FindUpdatedHistoryIndices(entity, recordHistoryCountCache, updatedHistoryIndices);
            recordHistoryCountCache.Clear();

            foreach (string histFieldName in updatedHistoryIndices.Keys)
            {
                foreach (int histIndex in updatedHistoryIndices[histFieldName])
                {
                    UpdateConversionHistory(action,
                                            recordDisplayName,
                                            CQHistoryMigrationItem.CreateHistoryItemVersion(histFieldName, histIndex),
                                            convRslt);
                }
            }
        }