private bool SetMandatoryFields(IMigrationAction action, ref OAdEntity newRecord, out List <string> processedFields)
        {
            XmlNodeList columns = action.MigrationActionDescription.SelectNodes("/WorkItemChanges/Columns/Column");

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

            StringBuilder updateLog = new StringBuilder();

            PrintUpdateLogHeader(action, updateLog);
            processedFields = new List <string>();

            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");


                OAdFieldInfo aFieldInfo        = CQWrapper.GetEntityFieldValue(newRecord, fieldName);
                int          fieldRequiredness = CQWrapper.GetRequiredness(aFieldInfo);
                if (fieldRequiredness != CQConstants.MANDATORY)
                {
                    // skipping all non-mandatory fields
                    continue;
                }

                string originalFieldValue = CQWrapper.GetFieldValue(aFieldInfo);

                int attempt1Count = 0;
                if (!SetFieldValue(action, newRecord, fieldName, stringVal, ref attempt1Count))
                {
                    return(false);
                }
                AddFieldToUpdateLog(fieldName, stringVal, updateLog);
                processedFields.Add(fieldName);
            }

            AddLineToUpdateLog(updateLog);
            int attempt2Count = 0;

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

            return(true);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="action"></param>
        /// <param name="convRslt"></param>
        /// <param name="stateTransitFieldNode"></param>
        /// <param name="skipFields"></param>
        /// <returns></returns>
        private bool ChangeRecordState(
            OAdEntity entity,
            IMigrationAction action,
            ConversionResult convRslt,
            XmlNode stateTransitFieldNode,
            out List <string> processedFields)
        {
            processedFields = new List <string>();

            string destState = UtilityMethods.ExtractSingleFieldValue(stateTransitFieldNode);

            Debug.Assert(!string.IsNullOrEmpty(destState), "string.IsNullOrEmpty(newState)");

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

            string entityDefName = CQWrapper.GetEntityDefName(entity);

            // find the current state
            OAdFieldInfo aFldInfo = CQWrapper.GetEntityFieldValue(entity, m_migrationContext.GetStateField(entityDefName));
            string       srcState = CQWrapper.GetFieldValue(aFldInfo);

            if (CQStringComparer.StateName.Equals(srcState, destState))
            {
                // state does not change, skip this action
                return(false);
            }

            // find action def name
            OAdEntityDef entityDef = CQWrapper.GetEntityDef(m_userSession, entityDefName);

            string[] changeActionNames = CQUtilityMethods.FindAllActionNameByTypeAndStateTransition(entityDef, srcState, destState, CQConstants.ACTION_CHANGE);

            if (changeActionNames.Length == 0)
            {
                // [teyang] todo error handling
                throw new InvalidOperationException();
            }

            string changeActionName = changeActionNames[0];

            // *********
            // 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);

            StringBuilder updateLog = new StringBuilder();

            PrintUpdateLogHeader(action, updateLog);

            // mark entity to be editable with the desired state-change action)
            CQWrapper.EditEntity(m_userSession, entity, changeActionName);

            XmlNodeList columns = action.MigrationActionDescription.SelectNodes("/WorkItemChanges/Columns/Column");

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

            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");


                OAdFieldInfo aFieldInfo        = CQWrapper.GetEntityFieldValue(entity, fieldName);
                int          fieldRequiredness = CQWrapper.GetRequiredness(aFieldInfo);
                if (fieldRequiredness != CQConstants.MANDATORY)
                {
                    // skipping all non-mandatory fields
                    continue;
                }

                int attempt1Count = 0;
                if (!SetFieldValue(action, entity, fieldName, stringVal, ref attempt1Count))
                {
                    return(false);
                }
                AddFieldToUpdateLog(fieldName, stringVal, updateLog);
                processedFields.Add(fieldName);
            }

            AddLineToUpdateLog(updateLog);
            int attempt2Count = 0;

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

            string retVal = CQWrapper.Validate(entity);

            if (!string.IsNullOrEmpty(retVal))
            {
                // [teyang] TODO conflict handling
                throw new InvalidOperationException(retVal);
            }

            retVal = CQWrapper.Commmit(entity);
            if (!string.IsNullOrEmpty(retVal))
            {
                // [teyang] TODO 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);
                }
            }

            return(true);
        }
        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);
                }
            }
        }