public static string[] FindAllChangeActionNamesByType( Session userSession, OAdEntity entity, int changeType) { // find the entity type OAdEntityDef entityDef = CQWrapper.GetEntityDef(userSession, CQWrapper.GetEntityDefName(entity)); // find the MODIFY action def name to open the record object[] actionDefNames = CQWrapper.GetActionDefNames(entityDef) as object[]; string[] allValidActionNames = CQUtilityMethods.FindActionNameByType(entityDef, actionDefNames, changeType); return(allValidActionNames); }
private string FindCQActionDefName( OAdEntityDef entityDef, int actionType) { // find the MODIFY action def name to open the record object[] actionDefNames = CQWrapper.GetActionDefNames(entityDef) as object[]; string[] modifyActionDefNames = CQUtilityMethods.FindActionNameByType(entityDef, actionDefNames, actionType); if (modifyActionDefNames.Length == 0) { // [teyang] todo error handling throw new InvalidOperationException(); } else if (modifyActionDefNames.Length > 1) { // [teyang] todo error handling throw new InvalidOperationException(); } else { return(modifyActionDefNames[0]); } }
public ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice( LinkService linkService, int maxDeltaSliceSize) { try { var linkChangeGroups = new List <LinkChangeGroup>(); if (null == ExtractLinkChangeActionsCallback) { return(linkChangeGroups.AsReadOnly()); } // load high watermark; as for CQ, we store local time for queries m_hwmLink.Reload(); DateTime hwmDeltaValue = m_hwmLink.Value; if (hwmDeltaValue.Equals(default(DateTime))) { hwmDeltaValue = new DateTime(1900, 1, 1); } hwmDeltaValue = hwmDeltaValue.AddSeconds(-1); // go back 1 second as we'll drop the millisec below string hwmDeltaValueStr = hwmDeltaValue.ToString(m_migrationContext.CQQueryDateTimeFormat, CultureInfo.InvariantCulture); // record current time to update HWM after processing DateTime newHwmValue = CQUtilityMethods.GetTimeForNewHighWaterMark(m_migrationContext.CQTimeOffsetFromServerHistoryTimesInMinutes); // store to be used for analysis WorkItemLinkStore store = new WorkItemLinkStore(m_configurationService.SourceId); // extract links var inMaxDeltaSliceSize = maxDeltaSliceSize; foreach (CQRecordFilter filter in m_filters) { CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreateQuery(m_userSession, filter, hwmDeltaValueStr, this); foreach (ClearQuestOleServer.OAdEntity record in recordQuery) { // HACK HACK if (record == null) { continue; } // HACK HACK string recDispName = CQWrapper.GetEntityDisplayName(record); TraceManager.TraceInformation("Generating linking delta for CQ Record: {0}", recDispName); var perWorkItemlinkChangeGroups = new List <LinkChangeGroup>(); ExtractLinkChangeActionsCallback(m_userSession, record, perWorkItemlinkChangeGroups); if (perWorkItemlinkChangeGroups.Count == 0) { TraceManager.TraceInformation("Number of links: {0}", 0); continue; } LinkChangeGroup consolidatedLinkChangeGroup = perWorkItemlinkChangeGroups[0]; for (int i = 1; i < perWorkItemlinkChangeGroups.Count; ++i) { foreach (LinkChangeAction action in perWorkItemlinkChangeGroups[i].Actions) { consolidatedLinkChangeGroup.AddChangeAction(action); } } TraceManager.TraceInformation("Number of links: {0}", consolidatedLinkChangeGroup.Actions.Count.ToString()); // VERY IMPORTANT STEP: update the link delta to store string hostRecMigrItemId = UtilityMethods.CreateCQRecordMigrationItemId(record); store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords( hostRecMigrItemId, consolidatedLinkChangeGroup, this); if (consolidatedLinkChangeGroup.Actions.Count > 0) { linkChangeGroups.Add(consolidatedLinkChangeGroup); } maxDeltaSliceSize -= consolidatedLinkChangeGroup.Actions.Count; if (maxDeltaSliceSize <= 0) { // size limit reached - persist groups to DB, then empty the slice and process next slice linkService.AddChangeGroups(linkChangeGroups); linkChangeGroups.Clear(); maxDeltaSliceSize = inMaxDeltaSliceSize; } } } // persist remaining groups to DB linkService.AddChangeGroups(linkChangeGroups); // clean up the returned link change group collection // when the caller (toolkit) receives an empty collection, it understands there is no more // delta to generate for the moment, and proceeds to next phase linkChangeGroups.Clear(); // update primary Highwater Mark m_hwmLink.Update(newHwmValue); TraceManager.TraceInformation("Persisted CQ linking HWM: {0}", ClearQuestConstants.CqLinkHwm); TraceManager.TraceInformation("Updated CQ linking HWM: {0}", newHwmValue.ToString()); return(linkChangeGroups.AsReadOnly()); } catch (Exception exception) { // [teyang] TODO CONFLICT HANDLING //MigrationConflict genericeConflict = WitGeneralConflictType.CreateConflict(exception); //var conflictManager = m_conflictManager.GetService(typeof(ConflictManager)) as ConflictManager; //Debug.Assert(null != conflictManager); //List<MigrationAction> resolutionActions; //ConflictResolutionResult resolveRslt = // conflictManager.TryResolveNewConflict(conflictManager.SourceId, genericeConflict, out resolutionActions); //Debug.Assert(!resolveRslt.Resolved); TraceManager.TraceException(exception); return(new List <LinkChangeGroup>().AsReadOnly()); } }
/// <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); }
public void GenerateDeltaTable() { try { if (!m_isLoginUserSQLEditor) { ValidateIsSQLEditor(); m_isLoginUserSQLEditor = true; } // load high watermark; as for CQ, we store local time for queries m_hwmDelta.Reload(); DateTime hwmDeltaValue = m_hwmDelta.Value; if (hwmDeltaValue.Equals(default(DateTime))) { hwmDeltaValue = new DateTime(1900, 1, 1); } hwmDeltaValue = hwmDeltaValue.AddSeconds(-1); // go back 1 second as we'll drop the millisec below m_migrationContext.CurrentHWMBaseLine = hwmDeltaValue; string hwmDeltaValueStr = hwmDeltaValue.ToString(m_migrationContext.CQQueryDateTimeFormat, CultureInfo.InvariantCulture); DateTime newHwmValue = CQUtilityMethods.GetTimeForNewHighWaterMark(m_migrationContext.CQTimeOffsetFromServerHistoryTimesInMinutes); foreach (CQRecordFilter filter in m_filters) { ComputeDeltaPerRecordType(filter, hwmDeltaValueStr); } // persist results and hwm TraceManager.TraceInformation("Promote delta to pending."); m_changeGroupService.PromoteDeltaToPending(); m_hwmDelta.Update(newHwmValue); TraceManager.TraceInformation("Persisted CQ HWM: {0}", ClearQuestConstants.CqRecordHwm); TraceManager.TraceInformation("Updated CQ HWM: {0}", newHwmValue.ToString()); } catch (ClearQuestInsufficientPrivilegeException privEx) { ConflictResolutionResult rslt = UtilityMethods.HandleInsufficientPriviledgeException(privEx, m_conflictManagerService); if (rslt.Resolved) { // todo: currently not expected, as we only enabled manual/skip resolution action } } catch (ClearQuestCOMDllNotFoundException cqComNotFoundEx) { UtilityMethods.HandleCOMDllNotFoundException(cqComNotFoundEx, ErrorManager, m_conflictManagerService); } catch (ClearQuestCOMCallException cqComCallEx) { UtilityMethods.HandleCQComCallException(cqComCallEx, ErrorManager, m_conflictManagerService); } catch (Exception ex) { ErrorManager errMgr = null; if (m_analysisServiceContainer != null) { errMgr = m_analysisServiceContainer.GetService(typeof(ErrorManager)) as ErrorManager; } UtilityMethods.HandleGeneralException(ex, errMgr, m_conflictManagerService); } }