Пример #1
0
        } // end of ProcessStatesAndTransitions

        /// <summary>
        /// Process the CQ properties for USER type field
        /// </summary>
        /// <param name="cqFieldType">ClearQuest field type</param>
        /// <param name="witField">WIT Field handle</param>
        /// <param name="fldMap">Field Map handle (will be populated with Field Map)</param>
        private void ProcessUserFieldProperties(int cqFieldType,
                                                FieldDefinition witField,
                                                ref FieldMapsFieldMap fldMap)
        {
            // set the type explicitly as string for user type field
            witField.type = CQConstants.WITFieldTypes[CQConstants.FIELD_SHORT_STRING];

            fldMap = new FieldMapsFieldMap();
            if (cqFieldType == CQConstants.FIELD_REFERENCE)
            {
                // set the VALIDUSER constraint only if its a single reference
                // for reference list of users, migrate as simple string field bug#399176
                witField.VALIDUSER     = new ValidUserRule();
                fldMap.ValueMaps       = new FieldMapsFieldMapValueMaps();
                fldMap.ValueMaps.refer = CQConstants.UserMapXMLValue;
            }
            else
            {
                string warningMsg = UtilityMethods.Format(CQResource.CQ_USER_LIST_CHANGED, witField.OldFieldName);
                ConverterMain.MigrationReport.WriteIssue(String.Empty, warningMsg,
                                                         CQWrapper.GetEntityDefName(this.cqEntity), null, IssueGroup.Witd.ToString(), ReportIssueType.Warning);

                Logger.Write(LogSource.CQ, TraceLevel.Warning, warningMsg);
            }

            // check only for requiredness for User field
            ProcessFieldProperties(witField, cqFieldType, true);

            fldMap.from    = witField.OldFieldName;
            fldMap.to      = witField.name; // new field name.. if changed
            fldMap.exclude = "false";
        }
Пример #2
0
        /// <summary>
        /// Parametrized Constructor for instantiating schema object
        /// No other CTors are provided as these values are required to start with
        /// </summary>
        /// <param name="xmlFile">Name of the target schema xml file</param>
        /// <param name="cqSess">Handle to valid CQ session</param>
        /// <param name="entityDef">Handle to valid CQ Entity Definition</param>
        public WITDXMLGenerator(string schemaXmlFile,
                                string fieldMapXmlFile,
                                Session cqSess,
                                OAdEntityDef entityDef,
                                VSTSConnection vstsConn)
        {
            Logger.EnteredMethod(LogSource.CQ, schemaXmlFile, fieldMapXmlFile,
                                 cqSess, entityDef);

            // create instance of WITDFieldMap to store field mappings
            witdFieldMap = new WITFieldMappings();

            // create instance of WITDSchema to store WITD schema
            witdSchema = new WITDSchema();
            witdSchema.SetApplication(Application.Workitemtypeeditor);

            // set the VSTS connection handle for finding the unique fields in VSTS system
            WITDSchema.VstsConn = vstsConn;

            // store file name to be used later to generate xml
            schemaXMLFileName   = schemaXmlFile;
            fieldMapXMLFileName = fieldMapXmlFile;

            cqEntityDef = entityDef;
            cqSession   = cqSess;
            cqEntity    = CQWrapper.BuildEntity(cqSession, CQWrapper.GetEntityDefName(cqEntityDef));

            Logger.ExitingMethod(LogSource.CQ);
        }
Пример #3
0
        }     // end of ValidateSchemaMapOnCQ

        /// <summary>
        /// Validates the Field Map on CQ for a Entity Type
        /// </summary>
        /// <param name="entityDef">Handle to Entity Definition</param>
        /// <param name="fldMaps">Deserialized Field Map data</param>
        /// <returns>true if successful, false in case of some error</returns>
        private static void ValidateFieldMapOnCQ(OAdEntityDef entityDef,
                                                 FieldMapsFieldMap[] fldMaps,
                                                 string fieldMapFile)
        {
            string entityName = CQWrapper.GetEntityDefName(entityDef);

            object[] cqFields = (object[])CQWrapper.GetFieldDefNames(entityDef);
            // prepare the list of fields from the current entity type
            Dictionary <string, bool> cqFieldsList = new Dictionary <string, bool>(TFStringComparer.OrdinalIgnoreCase);

            foreach (string cqFld in cqFields)
            {
                cqFieldsList.Add(cqFld, false);
            }

            Display.StartProgressDisplay(UtilityMethods.Format(CQResource.CQ_VALIDATE_FLD_MAP, fieldMapFile));
            try
            {
                StringBuilder invalidFields = new StringBuilder();
                foreach (FieldMapsFieldMap fldMap in fldMaps)
                {
                    if (fldMap.exclude != null &&
                        !TFStringComparer.XmlAttributeValue.Equals(fldMap.exclude, "true") &&
                        !CQConstants.CQInternalFields.ContainsKey(fldMap.from))
                    {
                        // this is to be included in the selected fields for migration
                        if (!cqFieldsList.ContainsKey(fldMap.from))
                        {
                            if (invalidFields.Length > 0)
                            {
                                invalidFields.Append(", ");
                            }
                            invalidFields.Append(fldMap.from);
                        }
                    }
                }

                if (invalidFields.Length > 0)
                {
                    string errMsg = UtilityMethods.Format(CQResource.CQ_FLD_NOT_EXIST, Path.GetFileName(fieldMapFile),
                                                          invalidFields.ToString(), entityName);

                    PostMigrationReport.WriteIssue(null, null, RepStatus.Failed,
                                                   ReportIssueType.Critical, String.Empty,
                                                   entityName, IssueGroup.Witd, errMsg);

                    throw new ConverterException(errMsg);
                }
            }
            finally
            {
                Display.StopProgressDisplay();
                Display.NewLine();
            }
        }   // end of ValidateFieldMapOnCQ
Пример #4
0
        /// <summary>
        /// Create the WIT in XML and all the underlying subelements
        /// </summary>
        private void CreateWorkItemType()
        {
            Logger.EnteredMethod(LogSource.CQ);

            WorkItemType wit = new WorkItemType();

            wit.name = CQWrapper.GetEntityDefName(cqEntityDef);

            // set the WIT
            witdSchema.SetWorkItemType(wit);

            wit.FORM = new Form();

            // add Fields to this WIT
            ProcessFields(wit);

            // add Workflow to WIT
            switch (CQWrapper.GetEntityDefType(cqEntityDef))
            {
            case CQConstants.STATE_BASED:
            case CQConstants.STATE_OR_STATELESS:
            {
                Logger.Write(LogSource.CQ, TraceLevel.Info, "Workflow is either State Based or Stateless");
                ProcessWorkflow(wit);
                break;
            }

            case CQConstants.STATE_LESS:
            {
                // whatever is the type of state we have to generate the workflow information
                // as that is mandatory as per the XSD file rules.. so a dummy block for Workflow
                // will be generated
                Logger.Write(LogSource.CQ, TraceLevel.Info, "Workflow is Stateless. Adding Dummy Workflow");

                wit.WORKFLOW = new Workflow();
                CreateDummyWorkflow(wit.WORKFLOW);
                break;
            }
            }

            Logger.ExitingMethod(LogSource.CQ);
        }
Пример #5
0
        /// <summary>
        /// Generate the XML Schema based on the data processed
        /// </summary>
        private void GenerateXml()
        {
            string entityName = CQWrapper.GetEntityDefName(cqEntityDef);
            string infoMsg    = UtilityMethods.Format(CQResource.SchemaCreation, entityName);

            Logger.Write(LogSource.CQ, TraceLevel.Verbose, infoMsg);

            Display.StartProgressDisplay(infoMsg);
            try
            {
                witdSchema.GenerateWITDSchema(schemaXMLFileName);
                witdFieldMap.GenerateFieldMappings(fieldMapXMLFileName);

                // bug# 21768.. add the xml comment in witd and field map file
                if (fieldsToComment.Count > 0)
                {
                    string commentMsg = CQResource.CoreFieldComment;
                    // open both document in Xml DOM
                    XmlDocument witdDoc = new XmlDocument();
                    XmlReader   witdRdr = new XmlTextReader(schemaXMLFileName);
                    witdDoc.Load(witdRdr);
                    witdRdr.Close();

                    XmlDocument fldMapDoc = new XmlDocument();
                    XmlReader   fldMapRdr = new XmlTextReader(fieldMapXMLFileName);
                    fldMapDoc.Load(fldMapRdr);
                    fldMapRdr.Close();

                    XmlNamespaceManager nsm = new XmlNamespaceManager(witdDoc.NameTable);
                    nsm.AddNamespace("CQ", Const.WITDTypesNamespace);

                    XmlNode parentFldNode = witdDoc.SelectSingleNode(
                        String.Format("//CQ:{0}/{1}/{2}", Const.TagWitd, Const.TagWit, Const.TagFields), nsm);
                    XmlNode parentMapNode = fldMapDoc.SelectSingleNode(Const.TagFieldMaps);

                    foreach (string fldName in fieldsToComment)
                    {
                        XmlNode fldNode = parentFldNode.SelectSingleNode(
                            String.Format("/descendant::{0}[@{1} = '{2}']", Const.TagField, Const.TagName, fldName));
                        if (fldNode != null)
                        {
                            XmlComment comment = witdDoc.CreateComment(string.Format(commentMsg, fldName));
                            parentFldNode.InsertBefore(comment, fldNode);
                        }

                        XmlNode mapNode = parentMapNode.SelectSingleNode(
                            String.Format("/descendant::{0}[@{1} = '{2}']", Const.TagFieldMap, Const.TagTo, fldName));
                        if (mapNode != null)
                        {
                            XmlComment comment = fldMapDoc.CreateComment(string.Format(commentMsg, fldName));
                            parentMapNode.InsertBefore(comment, mapNode);
                        }
                    }

                    // write the modified schema file back
                    XmlTextWriter writer = new XmlTextWriter(schemaXMLFileName, null);
                    writer.Formatting = Formatting.Indented;
                    witdDoc.Save(writer);
                    writer.Close();

                    // write the modified field map file back
                    writer            = new XmlTextWriter(fieldMapXMLFileName, null);
                    writer.Formatting = Formatting.Indented;
                    fldMapDoc.Save(writer);
                    writer.Close();
                }
            }
            finally
            {
                Display.StopProgressDisplay();
            }
        } // end of Generatexml
Пример #6
0
        /// <summary>
        /// Process the field properties and add it in WITD
        /// </summary>
        /// <param name="witField">Handle to Field instance to process the properties</param>
        /// <param name="cqFieldType">ClearQuest field type</param>
        /// <param name="isUserField">Is it a user field</param>
        private void ProcessFieldProperties(FieldDefinition witField, int cqFieldType, bool isUserField)
        {
            Logger.EnteredMethod(LogSource.CQ, witField);
            switch (CQWrapper.GetEntityFieldRequiredness(cqEntity, witField.OldFieldName))
            {
            case CQConstants.MANDATORY:
            {
                PlainRule pRule = new PlainRule();
                witField.REQUIRED = pRule;
                break;
            }

            case CQConstants.READONLY:
            {
                // PlainRule pRule = new PlainRule();
                // witField.READONLY = pRule;
                string roMsg = UtilityMethods.Format(CQResource.CQ_FLD_READONLY_CHANGED, witField.OldFieldName);
                Logger.Write(LogSource.CQ, TraceLevel.Warning, roMsg);
                ConverterMain.MigrationReport.WriteIssue(String.Empty,
                                                         roMsg, CQWrapper.GetEntityDefName(this.cqEntity), null, IssueGroup.Witd.ToString(), ReportIssueType.Warning);
                break;
            }

            case CQConstants.OPTIONAL:
                // no handling for these behaviors
                break;

            case CQConstants.USEHOOK:
                // no handling for these behaviors
                string hookMsg = UtilityMethods.Format(CQResource.CQ_FLD_SKIP_HOOK, witField.OldFieldName);
                ConverterMain.MigrationReport.WriteIssue(String.Empty,
                                                         hookMsg, CQWrapper.GetEntityDefName(this.cqEntity), null, IssueGroup.Witd.ToString(), ReportIssueType.Warning);
                Logger.Write(LogSource.CQ, TraceLevel.Warning, hookMsg);
                break;
            }

            if (!isUserField)
            {
                int      choiceType = CQWrapper.GetFieldChoiceType(cqEntity, witField.OldFieldName);
                object[] choices    = (object[])CQWrapper.GetFieldChoiceList(cqEntity, witField.OldFieldName);
                ListRule choiceList = null;
                if (choices != null && choices.Length > 0)
                {
                    choiceList = new ListRule();
                    foreach (object ob in choices)
                    {
                        ListItem lItem = new ListItem();
                        lItem.value = (string)ob;
                        choiceList.WITDItems.Add(lItem);
                    }

                    // decide whether its ALLOWED or SUGGESTED list
                    if (choiceType == CQConstants.CLOSED_CHOICE &&
                        cqFieldType != CQConstants.FIELD_MULTILINE_STRING)
                    {
                        witField.ALLOWEDVALUES = choiceList;
                    }
                    else
                    {
                        // since currituck does not allow multi value list, for all such fields
                        // set the List Type to Suggested Values (instead of Allowed Values)
                        witField.SUGGESTEDVALUES = choiceList;
                    }

                    // if there is a field containing any of Suggested/Allowed/Prohibited
                    // values, the fieldtype has to be either string or integer..
                    // as per the CQ-Currituck field mappings, we map Multiline String
                    // to Plain Text..
                    // So if it is niether String nor Integer, Move it to String type..
                    if (witField.type != FieldType.String && witField.type != FieldType.Integer)
                    {
                        Logger.Write(LogSource.CQ, TraceLevel.Warning,
                                     "Converting Field {0} of type {1} to String type",
                                     witField.OldFieldName, witField.type);
                        witField.type = FieldType.String;
                    }
                }
            }

            Logger.ExitingMethod(LogSource.CQ);
        } // end of ProcessFieldProperties
Пример #7
0
        /// <summary>
        /// Process and add Fields to the WIT
        /// </summary>
        /// <param name="wit">Handle to WIT to add the fields</param>
        private void ProcessFields(WorkItemType wit)
        {
            Logger.EnteredMethod(LogSource.CQ, wit);

            // add vsts_sourcedb and vsts_sourceid fields
            FieldDefinition vstsIdField       = AddInternalFields(wit, CQConstants.IdFieldName, FieldType.Integer);
            FieldDefinition vstsSourceIdField = AddInternalFields(wit, CommonConstants.VSTSSrcIdField, FieldType.String);

            vstsSourceIdField.READONLY = new PlainRule();
            AddInternalFields(wit, CommonConstants.VSTSSrcDbField, FieldType.String);

            // add id and vsts_sourceid in form
            CreateDefaultControl(vstsIdField.name, vstsIdField.refname, FieldType.Integer, wit);
            CreateDefaultControl(CQConstants.SourceFieldLabel, vstsSourceIdField.refname, FieldType.String, wit);

            // get all the fields from CQ
            object[] cqFields = (object[])CQWrapper.GetFieldDefNames(cqEntityDef);

            FieldDefinition witField;

            if (cqFields.Length > 0)
            {
                foreach (object ob in cqFields)
                {
                    string fldName = (string)ob;
                    if (CQConstants.InternalFieldTypes.ContainsKey(fldName))
                    {
                        // these are internal clearquest fields
                        // we dont want to migrate these
                        Logger.Write(LogSource.CQ, TraceLevel.Info, "Skipping CQ Internal Field '{0}'", fldName);
                        continue;
                    }

                    int cqFieldType = CQWrapper.GetFieldDefType(cqEntityDef, fldName);

                    string suggestedFldMap = (string)CQConstants.SuggestedMap[fldName];
                    if (suggestedFldMap != null)
                    {
                        // this field name matched to one the suggested mappings to one of the core field
                        // generate the field in schema and also a field map for this..
                        witField = new FieldDefinition();
                        witField.OldFieldName = fldName;
                        witField.name         = suggestedFldMap;
                        witField.type         = CQConstants.WITFieldTypes[cqFieldType];

                        // use the core field refname and type
                        for (int coreFieldIndex = 0; coreFieldIndex < CQConstants.CurrituckCoreFields.Length; coreFieldIndex++)
                        {
                            string coreFieldName = CQConstants.CurrituckCoreFields[coreFieldIndex].Name;
                            if (TFStringComparer.WorkItemFieldFriendlyName.Equals(coreFieldName, suggestedFldMap))
                            {
                                // use the refname and type from the core fields
                                witField.refname = CQConstants.CurrituckCoreFields[coreFieldIndex].ReferenceName;
                                witField.type    = (FieldType)Enum.Parse(typeof(FieldType),
                                                                         CQConstants.CurrituckCoreFields[coreFieldIndex].FieldType.ToString());
                                break;
                            }
                        }

                        fieldsToComment.Add(witField.name);
                        wit.AddField(witField);

                        FieldMapsFieldMap fldMap = null;
                        // process the field properties to set rules for Required/Read Only and list of values
                        // check if it requires UserMap also
                        if (cqFieldType == CQConstants.FIELD_REFERENCE ||
                            cqFieldType == CQConstants.FIELD_REFERENCE_LIST)
                        {
                            OAdEntityDef refEntity = CQWrapper.GetFieldReferenceEntityDef(cqEntityDef, witField.OldFieldName);
                            if (TFStringComparer.WorkItemType.Equals(CQWrapper.GetEntityDefName(refEntity), "users"))
                            {
                                ProcessUserFieldProperties(cqFieldType, witField, ref fldMap);
                            }
                        }
                        else
                        {
                            ProcessFieldProperties(witField, cqFieldType, false);
                            fldMap         = new FieldMapsFieldMap();
                            fldMap.from    = witField.OldFieldName;
                            fldMap.to      = witField.name;
                            fldMap.exclude = "false";
                        }

                        Logger.Write(LogSource.CQ, TraceLevel.Info, "Using Suggested Field Map {0} to {1}",
                                     witField.OldFieldName, suggestedFldMap.ToString());
                        witdFieldMap.GetFieldMappings().AddFieldMap(fldMap);

                        if (TFStringComparer.WorkItemFieldFriendlyName.Equals(fldMap.to, VSTSConstants.DescriptionField))
                        {
                            CreateDefaultControl(witField.OldFieldName, witField.refname, FieldType.PlainText, wit);
                        }
                        else
                        {
                            CreateDefaultControl(witField.OldFieldName, witField.refname, FieldType.String, wit);
                        }
                        continue;
                    }


                    switch (cqFieldType)
                    {
                    case CQConstants.FIELD_ID:
                    case CQConstants.FIELD_SHORT_STRING:
                    case CQConstants.FIELD_MULTILINE_STRING:
                    case CQConstants.FIELD_INT:
                    case CQConstants.FIELD_DATE_TIME:
                    {
                        Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Migrating Field '{0}'", fldName);
                        witField = new FieldDefinition();
                        witField.OldFieldName = witField.name = fldName;
                        witField.type         = CQConstants.WITFieldTypes[cqFieldType];

                        // find the set of allowed values and populate in the xml
                        ProcessFieldProperties(witField, cqFieldType, false);

                        wit.AddField(witField);

                        FieldMapsFieldMap fldMap = new FieldMapsFieldMap();
                        fldMap.from    = witField.OldFieldName;
                        fldMap.to      = witField.name;    // new field name.. if changed
                        fldMap.exclude = "false";

                        // add the field map
                        witdFieldMap.GetFieldMappings().AddFieldMap(fldMap);

                        // add in FORM
                        CreateDefaultControl(witField.OldFieldName, witField.refname, witField.type, wit);
                    }
                    break;

                    case CQConstants.FIELD_REFERENCE_LIST:
                    case CQConstants.FIELD_REFERENCE:
                    {
                        // find the referenced entity name
                        OAdEntityDef refEntity = CQWrapper.GetFieldReferenceEntityDef(cqEntityDef, fldName);
                        if (TFStringComparer.WorkItemType.Equals(CQWrapper.GetEntityDefName(refEntity), "users"))
                        {
                            // add the refer keyword in the FieldMap file for this field
                            // and generate the field information for this field..
                            // as User is a core functionality in currituck..
                            // handle is in special way
                            // there are no chances that a "users" field will be of REFERENCE_LIST type..
                            // in case we see a requirement for REFERENCE_LIST also, add this code there also
                            Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Migrating User Field '{0}'", fldName);
                            FieldMapsFieldMap fldMap = null;
                            witField = new FieldDefinition();
                            witField.OldFieldName = witField.name = fldName;
                            ProcessUserFieldProperties(cqFieldType, witField, ref fldMap);

                            // add in FIELD, FieldMap and FORM
                            wit.AddField(witField);

                            // fix for bug# 15769
                            // set new "To" field name in the field map in case the field name got changed as part of AddField() call
                            fldMap.to = witField.name;

                            witdFieldMap.GetFieldMappings().AddFieldMap(fldMap);
                            CreateDefaultControl(witField.OldFieldName, witField.refname, witField.type, wit);
                        }
                    }
                    break;

                    case CQConstants.FIELD_STATE:
                    case CQConstants.FIELD_ATTACHMENT_LIST:
                    case CQConstants.FIELD_JOURNAL:
                    case CQConstants.FIELD_DBID:
                    case CQConstants.FIELD_STATETYPE:
                    case CQConstants.FIELD_RECORDTYPE:
                        // not migrating these fields as they are CQ internal fields
                        Logger.Write(LogSource.CQ, TraceLevel.Info, "Skipping the Field migration for Internal Field Type '{0}'",
                                     cqFieldType);
                        break;

                    default:
                        break;
                    } // switch (cqFieldType)
                }     // end of foreach (object ob in cqFields)
            }   //if (cqFields.Length > 0)
            else
            {
                Logger.Write(LogSource.CQ, TraceLevel.Warning, "No Fields present in the current Entity Definition '{0}'", wit.name);
            }

            // add all the core fields in the FIELDS section as these fields are being used in the FORM section
            // as per Currituck implementation, any field existing in FORM section has to be in the FIELDS also
            // even if it is a core field
            FieldDefinition coreFldDef = null;

            for (int coreFieldIndex = 0; coreFieldIndex < CQConstants.CurrituckCoreFields.Length; coreFieldIndex++)
            {
                string coreFieldName = CQConstants.CurrituckCoreFields[coreFieldIndex].Name;
                bool   fieldExist    = false;
                foreach (FieldDefinition fldDef in wit.FIELDS)
                {
                    if (TFStringComparer.WorkItemFieldFriendlyName.Equals(fldDef.name, coreFieldName))
                    {
                        fieldExist = true;
                        break;
                    }
                }

                if (fieldExist == true)
                {
                    // skip this field.. its already added in the FIELDS section
                    continue;
                }

                coreFldDef         = new FieldDefinition();
                coreFldDef.name    = coreFieldName;
                coreFldDef.refname = CQConstants.CurrituckCoreFields[coreFieldIndex].ReferenceName;
                coreFldDef.type    = (FieldType)Enum.Parse(typeof(FieldType),
                                                           CQConstants.CurrituckCoreFields[coreFieldIndex].FieldType.ToString());

                if (coreFieldIndex < CQConstants.NoOfUserFldsInCoreFields)
                {
                    //add VALIDUSER rule for all user fields
                    coreFldDef.VALIDUSER = new ValidUserRule();
                }

                wit.AddField(coreFldDef);
            }

            int         pos;
            ControlType reasonFld = wit.FindFieldInForm(CQConstants.ReasonField, out pos);

            if (reasonFld == null)
            {
                // Bug# 50492: reason field is not yet added .. add it after the State field
                // look for state field position
                wit.FindFieldInForm(CQConstants.StateField, out pos);
                if (pos >= 0)
                {
                    FieldDefinition reasonFldDef = AddInternalFields(wit, CQConstants.ReasonFieldName, FieldType.String);
                    wit.FORM.Layout.WITDItems.Insert(pos + 1, CreateDefaultControl(reasonFldDef.name, CQConstants.ReasonField, FieldType.String, null));
                }
            }

            Logger.ExitingMethod(LogSource.CQ);
        } // end of ProcessFields
Пример #8
0
        } // end of CQEntityRec CTor

        /// <summary>
        /// Populate the current record from CQ if its not already in Currituck
        /// and also process all its references (recursively), Links, History and Attachments
        /// Else just sets the currituck id for future reference
        /// </summary>
        public bool Populate()
        {
            bool partiallyMigrated = false;
            // first check if it exists in the memory cache
            CQEntity    currentEntityRecords = m_cqParams.entityRecords[m_entityName];
            CQEntityRec lookupEntity         = currentEntityRecords.FindEntityRec(m_entityName, m_dbid);

            if (lookupEntity != null)
            {
                // record already populated..
                Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Already populated record '{0}' for Entity '{1}', DBID:{2}",
                             lookupEntity.SourceId, lookupEntity.EntityName, lookupEntity.DBID);
                return(true);
            }

            m_CQEntity = CQWrapper.GetEntityByDbId(m_cqParams.cqSession, m_entityName, m_dbid);

            // get the source id
            m_sourceId = CQWrapper.GetEntityDisplayName(m_CQEntity);
            Logger.Write(LogSource.CQ, TraceLevel.Verbose, UtilityMethods.Format(CQResource.CQ_PROCESSING_REC, m_sourceId));

            // check if it exist in currituck using static API
            VSTSWorkItemHelper wiHelper  = (VSTSWorkItemHelper)m_MySchemaMap.vstsHelper;
            ArrayList          checkList = new ArrayList();

            checkList.Add(new WorkItemNameValueRelation(CommonConstants.VSTSSrcIdField, m_sourceId));
            checkList.Add(new WorkItemNameValueRelation(CommonConstants.VSTSSrcDbField, m_cqParams.uniqueInstId));

            wiHelper = (VSTSWorkItemHelper)m_MySchemaMap.vstsHelper;
            if (wiHelper.IsWIMigrated(checkList) == true)
            {
                // need not to load the data from CQ..
                // just set the currituck id
                // not going to update this bug from CQ->Currituck even
                // if it is updated.. just get out from here as my population is done
                // with minimal required stuff
                string warningMsg = UtilityMethods.Format(CQResource.CQ_REC_MIGRATED, m_sourceId);
                Logger.Write(LogSource.CQ, TraceLevel.Warning, warningMsg);
                PostMigrationReport.WriteIssue(m_MySchemaMap.entity, m_MySchemaMap.WIT,
                                               Stats.MigrationStatus.Skipped,
                                               ReportIssueType.Warning,
                                               String.Empty,
                                               m_sourceId, IssueGroup.Wi, warningMsg);

                m_WITId = wiHelper.WorkItemId;
                //compact current object
                CompactMe();
                return(true);
            }
            else if (wiHelper.IsCurrentWorkItemValid() == true)
            {
                // work item is already there.. partially migrated
                partiallyMigrated = true;
            }

#if DEBUG
            CommonConstants.NoOfBugs++;
#endif
            // create the required data structures
            m_imWorkItem = new InMemoryWorkItem();
            string fldName;

            OAdEntityDef curEntityDef = CQWrapper.GetEntityDef(m_cqParams.cqSession, m_entityName);
            Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Adding record for Entity {0}, Record {1}",
                         m_entityName, CQWrapper.GetEntityDisplayName(m_CQEntity));

            object[] fields = (object[])CQWrapper.GetEntityFieldNames(m_CQEntity);
            foreach (object fld in fields)
            {
                fldName = (string)fld;
                if (CQConstants.InternalFieldTypes.ContainsKey(fldName))
                {
                    // these are internal clearquest fields
                    // we dont want to migrate these
                    Logger.Write(LogSource.CQ, TraceLevel.Info, "Skipping Internal Field '{0}' while migrating data for entity {1}",
                                 fldName, m_entityName);
                    continue;
                }
                {
                    // process this field only if it exists in the "from" side of Field Map
                    OAdFieldInfo fldInfo     = CQWrapper.GetEntityFieldValue(m_CQEntity, fldName);
                    int          cqFieldType = CQWrapper.GetFieldType(fldInfo);

                    switch (cqFieldType)
                    {
                    case CQConstants.FIELD_ID:
                    case CQConstants.FIELD_SHORT_STRING:
                    case CQConstants.FIELD_INT:
                    {
                        string fldValue = CQWrapper.GetFieldValue(fldInfo);
                        if (fldValue != null)
                        {
                            m_imWorkItem.InitialView.Add(fldName, fldValue);
                        }
                    }
                    break;

                    case CQConstants.FIELD_MULTILINE_STRING:
                    {
                        string fldValue = CQWrapper.GetFieldValue(fldInfo);
                        if (currentEntityRecords.Entity == null)
                        {
                            // build entity to get the list of allowed/suggested values
                            currentEntityRecords.Entity = CQWrapper.BuildEntity(m_cqParams.cqSession, currentEntityRecords.EntityName);
                        }
                        object[] choices = (object[])CQWrapper.GetFieldChoiceList(currentEntityRecords.Entity, fldName);
                        if (choices != null && choices.Length > 0)
                        {
                            // Multi Line String with List of Allowed/Suggested Values.. replace all '\n' with comma
                            // fix for bug# 429098
                            if (fldValue != null)
                            {
                                fldValue = fldValue.Replace("\n", ",");
                            }
                        }

                        /* no conversion shall be required.. bug# 20219 - shall be rendered in HTML as it is
                         *  // hack for Notes_Log & Description field.. Shall be converted to HTML (bug#429032)
                         *  if (fldName.Equals("Notes_Log", StringComparison.OrdinalIgnoreCase) ||
                         *      fldName.Equals("Description", StringComparison.OrdinalIgnoreCase))
                         *  {
                         *      fldValue = VSTSUtil.ConvertTextToHtml(fldValue);
                         *  }
                         */
                        m_imWorkItem.InitialView.Add(fldName, fldValue);
                    }
                    break;

                    case CQConstants.FIELD_DATE_TIME:
                    {
                        string fldValue = CQWrapper.GetFieldValue(fldInfo);
                        if (fldValue != null)
                        {
                            // the time returned from CQ API is the local time..
                            DateTime fldVal = DateTime.Parse(fldValue, CultureInfo.CurrentCulture);

                            //convert it in UTC
                            DateTime utcTime = CQConverterUtil.ConvertLocalToUTC(fldVal);
                            Logger.Write(LogSource.CQ, TraceLevel.Verbose,
                                         "Field [{0}], CQ Time [{1}], UTC Time [{2}]",
                                         fldName, fldVal.ToString(), utcTime.ToString());

                            m_imWorkItem.InitialView.Add(fldName, utcTime);
                        }
                        else
                        {
                            Logger.Write(LogSource.CQ, TraceLevel.Info, "Got null value for field {0}", fldName);
                        }
                    }
                    break;

                    case CQConstants.FIELD_REFERENCE:
                    {
                        // get the current entity def handle
                        OAdEntityDef refEntityDef  = CQWrapper.GetFieldReferenceEntityDef(curEntityDef, fldName);
                        string       refEntityName = CQWrapper.GetEntityDefName(refEntityDef);

                        // special handling for users.. add the user field value also..
                        // we dont want to create a link in this case..
                        // just add the field value pair in IMWorkItem.. and
                        // user map will be applied while saving
                        if (TFStringComparer.WorkItemType.Equals(refEntityName, "users"))
                        {
                            if (CQWrapper.GetFieldValueStatus(fldInfo) == (int)CQConstants.FieldStatus.HAS_VALUE)
                            {
                                // single value required
                                string refFldVal = CQWrapper.GetFieldValue(fldInfo);
                                m_imWorkItem.InitialView.Add(fldName, refFldVal);
                            }
                        }
                        else if (m_cqParams.allowedEntities.ContainsKey(refEntityName))
                        {
                            int valueStatus = CQWrapper.GetFieldValueStatus(fldInfo);
                            Logger.WriteIf((valueStatus != (int)CQConstants.FieldStatus.HAS_VALUE), LogSource.CQ,
                                           TraceLevel.Info, "No Value for Referenced field {0} in Entity {1}",
                                           refEntityName, m_entityName);
                            if (valueStatus == (int)CQConstants.FieldStatus.HAS_VALUE)
                            {
                                // single value required
                                string refFldVal = CQWrapper.GetFieldValue(fldInfo);
                                if (String.Equals(refFldVal, SourceId, StringComparison.Ordinal))
                                {
                                    // reference to self.. cannot have a link on to self
                                    string warningMsg = UtilityMethods.Format(CQResource.CQ_SELF_REFERENCE, SourceId, EntityName, fldName);
                                    Logger.Write(LogSource.CQ, TraceLevel.Warning, warningMsg);
                                    PostMigrationReport.WriteIssue(m_MySchemaMap.entity, m_MySchemaMap.WIT,
                                                                   Stats.MigrationStatus.Warning,
                                                                   ReportIssueType.Warning,
                                                                   String.Empty,
                                                                   m_sourceId, IssueGroup.Wi, warningMsg
                                                                   );
                                }
                                else
                                {
                                    m_referencedEntities.Add(new LinkRecord(refEntityName, refFldVal));
                                }
                            }
                        }
                    }
                    break;

                    case CQConstants.FIELD_REFERENCE_LIST:
                    {
                        // get the current entity def handle
                        OAdEntityDef refEntityDef  = CQWrapper.GetFieldReferenceEntityDef(curEntityDef, fldName);
                        string       refEntityName = CQWrapper.GetEntityDefName(refEntityDef);
                        // special handling for user list
                        // we dont want to create a link in this case..
                        // concatenate all the user names separated by comma
                        // NO USER MAP WILL BE APPLIED WHILE SAVING (bug#400276)
                        if (TFStringComparer.WorkItemType.Equals(refEntityName, "users"))
                        {
                            if (CQWrapper.GetFieldValueStatus(fldInfo) == (int)CQConstants.FieldStatus.HAS_VALUE)
                            {
                                object[]      refFldValues = CQWrapper.GetFieldValueAsList(fldInfo);
                                StringBuilder userList     = new StringBuilder();
                                for (int valueIndex = 0; valueIndex < refFldValues.Length; valueIndex++)
                                {
                                    object refFldObj = refFldValues[valueIndex];
                                    if (valueIndex > 0)
                                    {
                                        userList.Append(",");
                                    }

                                    userList.Append((string)refFldObj);
                                }
                                m_imWorkItem.InitialView.Add(fldName, userList.ToString());
                            }
                        }
                        else if (m_cqParams.allowedEntities.ContainsKey(refEntityName))
                        {
                            int valueStatus = CQWrapper.GetFieldValueStatus(fldInfo);
                            Logger.WriteIf((valueStatus != (int)CQConstants.FieldStatus.HAS_VALUE), LogSource.CQ,
                                           TraceLevel.Info, "No Value for Referenced field {0} in Entity {1}",
                                           fldName, m_entityName);
                            if (valueStatus == (int)CQConstants.FieldStatus.HAS_VALUE)
                            {
                                // value list expected
                                object[] refFldValues = CQWrapper.GetFieldValueAsList(fldInfo);
                                foreach (object refFldObj in refFldValues)
                                {
                                    string refFldVal = (string)refFldObj;
                                    if (String.Equals(refFldVal, SourceId, StringComparison.Ordinal))
                                    {
                                        // reference to self.. cannot have a link on to self
                                        string warningMsg = UtilityMethods.Format(CQResource.CQ_SELF_REFERENCE, SourceId, EntityName, fldName);
                                        Logger.Write(LogSource.CQ, TraceLevel.Warning, warningMsg);
                                        PostMigrationReport.WriteIssue(m_MySchemaMap.entity, m_MySchemaMap.WIT,
                                                                       Stats.MigrationStatus.Warning,
                                                                       ReportIssueType.Warning,
                                                                       String.Empty,
                                                                       m_sourceId, IssueGroup.Wi, warningMsg);
                                    }
                                    else
                                    {
                                        m_referencedEntities.Add(new LinkRecord(refEntityName, refFldVal));
                                    }
                                }
                            }
                        }
                    }
                    break;

                    case CQConstants.FIELD_ATTACHMENT_LIST:
                    case CQConstants.FIELD_STATE:
                    case CQConstants.FIELD_JOURNAL:
                    case CQConstants.FIELD_DBID:
                    case CQConstants.FIELD_STATETYPE:
                    case CQConstants.FIELD_RECORDTYPE:
                        Logger.Write(LogSource.CQ, TraceLevel.Info, "Skipping the Field migration for Internal Field Type '{0}'",
                                     cqFieldType);
                        // not migrating these fields as they are CQ internal fields
                        continue;

                    default:
                        Logger.Write(LogSource.CQ, TraceLevel.Info, "Skipping the Field migration for Unkknown Field Type '{0}'",
                                     cqFieldType);
                        break;
                    }
                }
            } // end of foreachfields

            // add the source id and db separately
            m_imWorkItem.InitialView.Add(CommonConstants.VSTSSrcIdField, m_sourceId);
            m_imWorkItem.InitialView.Add(CommonConstants.VSTSSrcDbField, m_cqParams.uniqueInstId);

            // use vstshelper to migrate the data
            wiHelper = (VSTSWorkItemHelper)m_MySchemaMap.vstsHelper;
            wiHelper.IsWIMigrated(checkList);

            // get attachments in the imworkitem
            ProcessAttachments();

            // history processing will use same imWorkItem for first history info
            // and create other history indexes
            int migratedHistory = 0;
            if (wiHelper.IsCurrentWorkItemValid())
            {
                migratedHistory = wiHelper.GetCurrentWorkItemHistoryCount();
                if (migratedHistory > 0)
                {
                    // We are going for incremental migration. And as we stuff first history item of a CQBug
                    // into InitialView itself, actual no. of migrated history is one more than the value of
                    // the "Migration Status" field. So increment by one.
                    ++migratedHistory;
                }
            }

            ArrayList historyItems = ProcessHistory(m_imWorkItem.InitialView, migratedHistory);

            Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Dumping initial view for {0}", m_sourceId);
            foreach (object key in m_imWorkItem.InitialView.Keys)
            {
                Logger.Write(LogSource.CQ, TraceLevel.Verbose, "{0} - {1}", key, m_imWorkItem.InitialView[key]);
            }

            bool initialViewStatus = true;
            try
            {
                if (!partiallyMigrated)
                {
                    // if some history items or links are left to be migrated.. leave the bug as opened..
                    if (historyItems.Count > 0 || m_referencedEntities.Count > 0)
                    {
                        Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Creating initial view of {0} .. {1} Histories, {2} Links pending",
                                     SourceId, historyItems.Count, m_referencedEntities.Count);
                        // create the record and keep it open for history editing
                        initialViewStatus = wiHelper.CreateInitialViewOfWorkItem(m_sourceId, m_imWorkItem, false);
                    }
                    else
                    {
                        Logger.Write(LogSource.CQ, TraceLevel.Verbose, "Creating initial view of {0}", SourceId);
                        // create all the entries in the record and set the status to done
                        initialViewStatus = wiHelper.CreateInitialViewOfWorkItem(m_sourceId, m_imWorkItem, true);
                    }
                }
            }
            catch (Exception ex)
            {
                // creation of work item failed
                string errMsg = UtilityMethods.Format(CQResource.CQ_WI_CREATION_FAILED, SourceId, ex.Message);
                CQConverter.ReportWorkItemFailure(errMsg, SourceId, m_MySchemaMap.entity, m_MySchemaMap.WIT,
                                                  m_cqParams.exitOnError);
                if (m_cqParams.exitOnError == true)
                {
                    throw new ConverterException(errMsg);
                }
                else
                {
                    // continue with another work item
                    // need to skip this work item..
                    m_WITId = -1;
                    CompactMe();
                    return(false);
                }
            }
            finally
            {
            }

            // get back currituck id and store in this
            m_WITId = wiHelper.WorkItemId;

            // store the handle of work item to restore the state of work item helper back to
            // working work item which may get changed because of processing links recursively
            object workItem = wiHelper.GetCurrentWorkItem();

            // before processing history, clean out attachments.. only if its already migrated
            if (wiHelper.GetCurrentWorkItemAttachmentsCount() == m_imWorkItem.Attachments.Count)
            {
                m_imWorkItem.Attachments.Clear();
            }

            // add all the links now so that they go as part of history
            bool refRecordStatus = true;
            foreach (LinkRecord linkRec in m_referencedEntities)
            {
                if (AddReferenceRecord(linkRec) == false)
                {
                    refRecordStatus = false; // once false always false
                }
            }

            // process duplicate records
            if (ProcessDuplicates(m_cqParams) == false)
            {
                refRecordStatus = false;
            }

            bool writeHistoryPassed = true;
            wiHelper.SetCurrentWorkItem(workItem);
            if (historyItems.Count > 0 || m_imWorkItem.Links.Count > 0 || m_imWorkItem.Attachments.Count > 0)
            {
                m_imWorkItem.HistoryItems = historyItems;

                try
                {
                    writeHistoryPassed = wiHelper.WriteHistoryItems(m_sourceId, m_imWorkItem,
                                                                    refRecordStatus && initialViewStatus);
                    if (!writeHistoryPassed)
                    {
                        // Bug#59861: In the case of the partially migrated bug,
                        // converter says all bugs migrated successfully in
                        // summary, but in error section it says one bug  failed
                        // due to attachment size issue. This issue has already
                        // been written to the report. Just need to update the
                        // statistics info.
                        PostMigrationReport.WriteIssue(m_MySchemaMap.entity,
                                                       m_MySchemaMap.WIT,
                                                       Stats.MigrationStatus.Failed,
                                                       ReportIssueType.Info,
                                                       null, m_sourceId, IssueGroup.Wi,
                                                       null);
                    }
                    // set the bug migration status to done only if there were no
                    // problems with  initial view and any of the references
                    if ((!writeHistoryPassed || !refRecordStatus || !initialViewStatus) &&
                        m_cqParams.exitOnError)
                    {
                        // stop processing more records
                        CompactMe();
                        return(false);
                    }
                }
                catch (Exception ex)
                {
                    // creation of history failed
                    string errMsg = UtilityMethods.Format(CQResource.CQ_WI_MIG_FAILED, SourceId, ex.Message);
                    CQConverter.ReportWorkItemFailure(errMsg, SourceId, m_MySchemaMap.entity, m_MySchemaMap.WIT,
                                                      m_cqParams.exitOnError);
                    if (m_cqParams.exitOnError == true)
                    {
                        throw new ConverterException(errMsg);
                    }
                    else
                    {
                        // continue with another work item.. reporting this failure
                        CompactMe();
                        return(false);
                    }
                } // end of catch
                finally
                {
                }
            } // end of history items processing

            // add to pass count
            ConverterMain.MigrationReport.Statistics.NumberOfItems++;

            // add to per work item type section
            if (writeHistoryPassed)
            {
                PostMigrationReport.WriteIssue(m_MySchemaMap.entity, m_MySchemaMap.WIT,
                                               Stats.MigrationStatus.Passed,
                                               ReportIssueType.Info,
                                               null, m_sourceId, IssueGroup.Wi, null);
            }
            //compact current object
            CompactMe();
            return(true);
        } // end of Populate()
Пример #9
0
        private void MapLinkTypes(string[] refEntities, string entityToMigrate, OAdEntityDef entityDef)
        {
            List <string> refEntityList = new List <string>(refEntities);

            object[] fieldDefNameObjs = CQWrapper.GetFieldDefNames(entityDef) as object[];

            // add the field reference[list] links
            foreach (object fieldDefNameObj in fieldDefNameObjs)
            {
                string fieldDefName = fieldDefNameObj as string;
                int    fieldDefType = CQWrapper.GetFieldDefType(entityDef, fieldDefName);

                if (fieldDefType == CQConstants.FIELD_REFERENCE)
                {
                    OAdEntityDef childRecordEntityDef     = CQWrapper.GetFieldReferenceEntityDef(entityDef, fieldDefName);
                    string       childRecordEntityDefName = CQWrapper.GetEntityDefName(childRecordEntityDef);

                    if (refEntityList.Contains(childRecordEntityDefName))
                    {
                        var linkTypeMapping = new LinkingLinkTypeMapping();
                        linkTypeMapping.LeftMigrationSourceUniqueId  = "[Please add Left Migration Source Migration Id]";
                        linkTypeMapping.RightMigrationSourceUniqueId = "[Please add Right Migration Source Migration Id]";
                        linkTypeMapping.LeftLinkType = string.Format("ClearQuestAdapter.LinkType.ReferenceFieldRecordLink.{0}.{1}",
                                                                     entityToMigrate, childRecordEntityDef);
                        linkTypeMapping.RightLinkType = "[Please add Right link type reference name]";

                        if (!m_linkTypeMaps.ContainsKey(linkTypeMapping.LeftLinkType))
                        {
                            m_linkTypeMaps.Add(linkTypeMapping.LeftLinkType, linkTypeMapping);
                        }
                    }
                }
                else if (fieldDefType == CQConstants.FIELD_REFERENCE_LIST)
                {
                    OAdEntityDef childRecordEntityDef     = CQWrapper.GetFieldReferenceEntityDef(entityDef, fieldDefName);
                    string       childRecordEntityDefName = CQWrapper.GetEntityDefName(childRecordEntityDef);

                    if (refEntityList.Contains(childRecordEntityDefName))
                    {
                        var linkTypeMapping = new LinkingLinkTypeMapping();
                        linkTypeMapping.LeftMigrationSourceUniqueId  = "[Please add Left Migration Source Migration Id]";
                        linkTypeMapping.RightMigrationSourceUniqueId = "[Please add Right Migration Source Migration Id]";
                        linkTypeMapping.LeftLinkType = string.Format("ClearQuestAdapter.LinkType.ReferenceListFieldRecordLink.{0}.{1}",
                                                                     entityToMigrate, childRecordEntityDef);
                        linkTypeMapping.RightLinkType = "[Please add Right link type reference name]";

                        if (!m_linkTypeMaps.ContainsKey(linkTypeMapping.LeftLinkType))
                        {
                            m_linkTypeMaps.Add(linkTypeMapping.LeftLinkType, linkTypeMapping);
                        }
                    }
                }
            }

            // add the duplicate links
            var duplinkTypeMapping = new LinkingLinkTypeMapping();

            duplinkTypeMapping.LeftMigrationSourceUniqueId  = "[Please add Left Migration Source Migration Id]";
            duplinkTypeMapping.RightMigrationSourceUniqueId = "[Please add Right Migration Source Migration Id]";
            duplinkTypeMapping.LeftLinkType  = "ClearQuestAdapter.LinkType.Duplicate";
            duplinkTypeMapping.RightLinkType = "[Please add Right link type reference name]";
            if (!m_linkTypeMaps.ContainsKey(duplinkTypeMapping.LeftLinkType))
            {
                m_linkTypeMaps.Add(duplinkTypeMapping.LeftLinkType, duplinkTypeMapping);
            }
        }