/// <summary> /// Enumerate the diff items found based on the query passed in as well as the filterString and version passed /// to InitializeForDiff. The return type is IEnumerable<> so that adapter implementations do not need download and keep /// all of the IWITDiffItems in memory at once. /// </summary> /// <param name="queryCondition">A string that specifies a query used to select a subset of the work items defined by /// the set that the filter string identified.</param> /// <returns>An enumeration of IWITDiffItems each representing a work item to be compared by the WIT Diff operation</returns> public IEnumerable <IWITDiffItem> GetWITDiffItems(string queryCondition) { if (m_getWITDiffItemsDone) { yield break; } if (m_cqRecordFilter is CQRecordStoredQueryFilter) { if (!string.IsNullOrEmpty(queryCondition)) { throw new NotImplementedException("Query conditions on the ServerDiff operation are not supported with ClearQuest stored queries are used"); } } else { if (!string.IsNullOrEmpty(queryCondition)) { m_cqRecordFilter = new CQRecordFilter(m_cqRecordFilter.RecordType, m_cqRecordFilter.SelectFromTable, queryCondition); } } CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreateQuery(m_userSession, m_cqRecordFilter, null, this); foreach (OAdEntity record in recordQuery) { if (record != null) // this if check is HACK { OAdHistoryFields histFields = CQWrapper.GetHistoryFields(record); int historyFldCount = CQWrapper.HistoryFieldsCount(histFields); yield return(new CQWITDiffItem(this, record, historyFldCount - 1)); } } m_getWITDiffItemsDone = true; }
internal static OAdHistoryField HistoryFieldsItem(OAdHistoryFields histFields, ref object item) { OAdHistoryField retval = null; try { retval = (OAdHistoryField)histFields.item(ref item); } catch (COMException ex) { InteropErrorHandler.HandleCQException(ex); } return(retval); }
internal static int HistoryFieldsCount(OAdHistoryFields histFields) { int retval = 0; try { retval = histFields.Count; } catch (COMException ex) { InteropErrorHandler.HandleCQException(ex); } return(retval); }
internal static OAdHistoryFields GetHistoryFields(OAdEntity cqEntity) { OAdHistoryFields histFields = null; try { histFields = (OAdHistoryFields)cqEntity.HistoryFields; } catch (COMException ex) { InteropErrorHandler.HandleCQException(ex); } return(histFields); }
private void BuildRecordHistoryCountCache( OAdEntity aRecord, Dictionary <string, int> recordHistoryCountCache) { OAdHistoryFields aHistFields = CQWrapper.GetHistoryFields(aRecord); int historyFldCount = CQWrapper.HistoryFieldsCount(aHistFields); for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField aHistoryField = CQWrapper.HistoryFieldsItem(aHistFields, ref ob); string historyFieldName = CQWrapper.GetHistoryFieldName(aHistoryField); int historyCount = CQWrapper.HistoryFieldHistoriesCount(aHistoryField); recordHistoryCountCache.Add(historyFieldName, historyCount); } }
/// <summary> /// Enumerate the diff items found based on the query passed in as well as the filterString and version passed /// to InitializeForDiff. The return type is IEnumerable<> so that adapter implementations do not need download and keep /// all of the IWITDiffItems in memory at once. /// </summary> /// <param name="queryCondition">A string that specifies a query used to select a subset of the work items defined by /// the set that the filter string identified.</param> /// <returns>An enumeration of IWITDiffItems each representing a work item to be compared by the WIT Diff operation</returns> public IEnumerable <IWITDiffItem> GetWITDiffItems(string queryCondition) { List <CQRecordFilter> recordFilters = new List <CQRecordFilter>(); recordFilters.Add(m_cqRecordFilter); if (!string.IsNullOrEmpty(queryCondition)) { CQRecordFilter queryConditionRecordFilter = new CQRecordFilter(m_cqRecordFilter.RecordType, m_cqRecordFilter.SelectFromTable, queryCondition); recordFilters.Add(queryConditionRecordFilter); } CQRecordSqlQuery recordQuery = new CQRecordSqlQuery(m_userSession, recordFilters, null, this); foreach (OAdEntity record in recordQuery) { if (record != null) // this if check is HACK { OAdHistoryFields histFields = CQWrapper.GetHistoryFields(record); int historyFldCount = CQWrapper.HistoryFieldsCount(histFields); yield return(new CQWITDiffItem(this, record, historyFldCount - 1)); } } }
internal static void FindLastRevDtls(OAdEntity record, out string lastAuthor, out DateTime lastChangeDate) { lastAuthor = string.Empty; lastChangeDate = DateTime.MinValue; OAdHistoryFields cqHistFields = CQWrapper.GetHistoryFields(record); int historyFldCount = CQWrapper.HistoryFieldsCount(cqHistFields); for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField historyField = CQWrapper.HistoryFieldsItem(cqHistFields, ref ob); int historyCount = CQWrapper.HistoryFieldHistoriesCount(historyField); // pick the last history for each historyfield object obHistIndex = (object)(historyCount - 1); OAdHistory aHistory = CQWrapper.HistoryFieldHistoriesItem(historyField, ref obHistIndex); CQHistory cqHistory = new CQHistory(aHistory); // CQ API returns local time DateTime changedDate = DateTime.Parse(cqHistory.Date, CultureInfo.CurrentCulture); if (changedDate.CompareTo(lastChangeDate) > 0) { // found a later change lastChangeDate = changedDate; lastAuthor = cqHistory.User; } } if (lastChangeDate.CompareTo(DateTime.MinValue) == 0) { lastChangeDate = DateTime.Now; lastAuthor = Environment.UserDomainName + "\\" + Environment.UserName; } }
private void FindUpdatedHistoryIndices( OAdEntity aRecord, Dictionary <string, int> recordHistoryCountCache, Dictionary <string, int[]> updatedHistoryIndices) { OAdHistoryFields aHistFields = CQWrapper.GetHistoryFields(aRecord); int historyFldCount = CQWrapper.HistoryFieldsCount(aHistFields); for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField aHistoryField = CQWrapper.HistoryFieldsItem(aHistFields, ref ob); string historyFieldName = CQWrapper.GetHistoryFieldName(aHistoryField); int latestHistoryCount = CQWrapper.HistoryFieldHistoriesCount(aHistoryField); int oldHistoryCount; if (recordHistoryCountCache.ContainsKey(historyFieldName)) { oldHistoryCount = recordHistoryCountCache[historyFieldName]; } else { oldHistoryCount = 0; } int numOfNewHistory = latestHistoryCount - oldHistoryCount; if (numOfNewHistory > 0) { updatedHistoryIndices.Add(historyFieldName, new int[numOfNewHistory]); for (int i = 0; i < numOfNewHistory; ++i) { updatedHistoryIndices[historyFieldName][i] = oldHistoryCount + i; } } } }
private void ComputeDeltaPerRecord( OAdEntity aRecord) { OAdEntityDef aEntityDef = CQWrapper.GetEntityDef(m_userSession, CQWrapper.GetEntityDefName(aRecord)); string recordDispName = CQWrapper.GetEntityDisplayName(aRecord); string recordEntDefName = CQWrapper.GetEntityDefName(aRecord); #region process history bool recordContentIsModified = false; bool maybeNewRecord = false; Dictionary <string, List <ClearQuestRecordItem> > historyDelta = new Dictionary <string, List <ClearQuestRecordItem> >(); Dictionary <string, int> perHistoryFieldLastIndex = new Dictionary <string, int>(); // needed for updating processed delta // find all history fields OAdHistoryFields aHistFields = CQWrapper.GetHistoryFields(aRecord); int historyFldCount = CQWrapper.HistoryFieldsCount(aHistFields); bool containsNewHistory = false; for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField aHistoryField = CQWrapper.HistoryFieldsItem(aHistFields, ref ob); string historyFieldName = CQWrapper.GetHistoryFieldName(aHistoryField); // find last processed history entry for this history field string lookupItemId = CQDeltaComputationProgressLookupService.CreateHistoryItemId(recordEntDefName, recordDispName, historyFieldName); int startHistIndex = 1 + DeltaComputeProgressService.GetLastProcessedItemVersion(lookupItemId); // find all history in a particular history field int historyCount = CQWrapper.HistoryFieldHistoriesCount(aHistoryField); for (int histIndex = startHistIndex; histIndex < historyCount; histIndex++) { object obHistIndex = (object)histIndex; OAdHistory aHistory = CQWrapper.HistoryFieldHistoriesItem(aHistoryField, ref obHistIndex); CQHistory cqHistory = new CQHistory(aHistory); CQMigrationItem migrationItem = new CQHistoryMigrationItem(recordDispName, historyFieldName, histIndex); if (TranslationService.IsSyncGeneratedItemVersion(ClearQuestRecordItem.GetMigrationRecordId(recordEntDefName, recordDispName), migrationItem.MigrationItemVersion, m_configurationService.SourceId)) { continue; } if (histIndex == 0) { maybeNewRecord = true; } // add unprocessed history fields for processing if (!historyDelta.ContainsKey(historyFieldName)) { historyDelta.Add(historyFieldName, new List <ClearQuestRecordItem>(historyCount)); } historyDelta[aHistoryField.fieldname].Add(new ClearQuestRecordItem(aRecord, aHistory, historyFieldName, histIndex.ToString())); containsNewHistory = true; // based on action type, we decide whether content change is needed int actionType = CQWrapper.GetActionDefType(aEntityDef, cqHistory.Action); switch (actionType) { case CQConstants.ACTION_SUBMIT: break; case CQConstants.ACTION_MODIFY: recordContentIsModified = true; break; case CQConstants.ACTION_CHANGE: break; case CQConstants.ACTION_DUPLICATE: break; case CQConstants.ACTION_UNDUPLICATE: break; case CQConstants.ACTION_IMPORT: break; case CQConstants.ACTION_DELETE: TraceManager.TraceInformation(ClearQuestResource.ClearQuest_Msg_RecordDeleted, recordEntDefName, recordDispName); break; case CQConstants.ACTION_BASE: break; case CQConstants.ACTION_RECORD_SCRIPT_ALIAS: break; } } perHistoryFieldLastIndex.Add(historyFieldName, historyCount - 1); } #endregion #region generate delta for content and history if (maybeNewRecord || recordContentIsModified) { // the first revision, i.e. "Submit", of a CQ record is always hard-coded to be '1' CQMigrationItem contentMigrationAction = new CQMigrationItem(recordDispName, ClearQuestRecordItem.NewRecordVersion); bool isNewRecord = false; if (maybeNewRecord) { isNewRecord = !(DeltaComputeProgressService.IsMigrationItemProcessed(recordDispName, ClearQuestRecordItem.NewRecordVersionValue)); } if (!isNewRecord) { // all subsequent record "MODIFICATIONs" are hard-coded to be "update@<Now.Ticks>" contentMigrationAction.MigrationItemVersion = ClearQuestRecordItem.RecordUpdateVersion + "@" + DateTime.Now.Ticks; } ClearQuestRecordItem recordContentItem = new ClearQuestRecordItem(aRecord, contentMigrationAction.MigrationItemVersion); recordContentItem.CQSession = m_userSession; recordContentItem.Version = contentMigrationAction.MigrationItemVersion; ChangeGroup contentChangeGroup = recordContentItem.CreateChangeGroup( m_changeGroupService, m_migrationContext, isNewRecord && m_isLastRevisionAutoCorrectionEnabled); contentChangeGroup.Save(); if (isNewRecord && !containsNewHistory) { DeltaComputeProgressService.UpdateCache(recordDispName, ClearQuestRecordItem.NewRecordVersionValue); } } var lastHistoryRecordItem = historyDelta[historyDelta.Keys.Last()].Last(); foreach (string histFieldName in historyDelta.Keys) { foreach (ClearQuestRecordItem recordHistItem in historyDelta[histFieldName]) { recordHistItem.CQSession = m_userSession; ChangeGroup changeGroup = recordHistItem.CreateChangeGroup( m_changeGroupService, m_migrationContext, (CQStringComparer.FieldName.Equals(recordHistItem.HistoryFieldName, lastHistoryRecordItem.HistoryFieldName) && recordHistItem.Version.Equals(lastHistoryRecordItem.Version, StringComparison.OrdinalIgnoreCase) && m_isLastRevisionAutoCorrectionEnabled)); changeGroup.Save(); } Debug.Assert(perHistoryFieldLastIndex.ContainsKey(histFieldName), "perHistoryFieldLastIndex.ContainsKey(histFieldName) returns false"); string deltaComputeProcessLookupId = CQDeltaComputationProgressLookupService.CreateHistoryItemId(recordEntDefName, recordDispName, histFieldName); DeltaComputeProgressService.UpdateCache(deltaComputeProcessLookupId, perHistoryFieldLastIndex[histFieldName]); } #endregion #region process attachment OAdAttachmentFields aAttachmentFields = CQWrapper.GetAttachmentFields(aRecord); for (int aAttachmentFieldsIndex = 0; aAttachmentFieldsIndex < CQWrapper.AttachmentsFieldsCount(aAttachmentFields); aAttachmentFieldsIndex++) { object ob = (object)aAttachmentFieldsIndex; OAdAttachmentField aAttachmentField = CQWrapper.AttachmentsFieldsItem(aAttachmentFields, ref ob); string fieldName = CQWrapper.GetAttachmentFieldName(aAttachmentField); ChangeGroup changeGroup = m_changeGroupService.CreateChangeGroupForDeltaTable( string.Format("{0}:{1}:{2}", recordDispName, "Attachments", fieldName)); // process all attachments OAdAttachments attachments = CQWrapper.GetAttachments(aAttachmentField); for (int attachmentIndex = 0; attachmentIndex < CQWrapper.AttachmentsCount(attachments); attachmentIndex++) { object obIndex = (object)attachmentIndex; OAdAttachment aAttachment = CQWrapper.AttachmentsItem(attachments, ref obIndex); ClearQuestAttachmentItem attachmentItem = new ClearQuestAttachmentItem(aRecord, aAttachmentField, aAttachment, UserSessionConnConfig); attachmentItem.CQSession = m_userSession; attachmentItem.CreateChangeAction(changeGroup, lastHistoryRecordItem.Version); } if (changeGroup.Actions.Count > 0) { changeGroup.Save(); } } #endregion }
} // end of Populate() /// <summary> /// Processes the history for current record. /// </summary> /// <param name="initialView">First history item structure</param> /// <param name="migratedHistory">No of history items already migrated</param> /// <returns>List of history items except first one</returns> private ArrayList ProcessHistory(Hashtable initialView, int migratedHistory) { int noOfHistory = 0; ArrayList historyItems = new ArrayList(); try { Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Processing History for {0} : {1}", m_entityName, m_sourceId); // record all history items except the first one Hashtable currentHistory = null; OAdHistoryFields cqHistFields = CQWrapper.GetHistoryFields(m_CQEntity); int historyFldCount = CQWrapper.HistoryFieldsCount(cqHistFields); for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField historyField = CQWrapper.HistoryFieldsItem(cqHistFields, ref ob); int historyCount = CQWrapper.HistoryFieldHistoriesCount(historyField); for (int histIndex = migratedHistory; histIndex < historyCount; histIndex++) { if (histIndex == 0) { // first history.. use the initial view to record history currentHistory = initialView; } else { // create a new instance to record history InMemoryHistoryItem imHistItem = new InMemoryHistoryItem(); historyItems.Add(imHistItem); currentHistory = imHistItem.UpdatedView; } object obHistIndex = (object)histIndex; OAdHistory aHistory = CQWrapper.HistoryFieldHistoriesItem(historyField, ref obHistIndex); string[] parsedString = CQWrapper.HistoryValue(aHistory).Split('\t'); Debug.Assert(parsedString != null && parsedString.Length >= 6); string date = parsedString[1]; string user = parsedString[2]; string action = parsedString[3]; string oldstate = parsedString[4]; string newstate = parsedString[5]; DateTime changedDate = DateTime.Parse(date, CultureInfo.CurrentCulture); Logger.Write(LogSource.CQ, TraceLevel.Verbose, "History Item : [{0}] [{1}] [{2}] [{3}]", changedDate, user, oldstate, newstate); string historyval = UtilityMethods.Format(CQResource.CQ_HISTORY_STRING, changedDate.ToString(CultureInfo.CurrentCulture), user, action, oldstate, newstate); currentHistory.Add("History", historyval); currentHistory.Add("user_name", user); currentHistory.Add("Reason", action); if (!String.Equals("N/A", newstate, StringComparison.Ordinal)) { // add state only if state is valid currentHistory.Add("State", newstate); } noOfHistory++; #if DEBUG CommonConstants.NoOfHistory++; #endif } } } finally { } return(historyItems); } // end of ProcessHistory()