private static int mapFromUpdated( Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem, EnterpriseChangeRequest newEcr, String fieldName) { int noOfMappedChanged = 0; // TODO: For the "calculated" fields we have defined ourselves we know the // dependencies, but should be expressed more elegant than this. Also the // Ericsson.Defect.User.DisplayName is dependent on System.AssignedTo but // will not be updated - we "know" that ... if (fieldName.Equals(TFSMapper.TFS_OWNER)) { fieldName = TFSMapper.ERICSSON_DEFECT_USER_SIGNUM; } // Can be multiple ECR properties updated by one TFS field List <Property> props = props = AttributesMapper.getInstance().getNotifyProperties(fieldName); if (props != null && props.Count > 0) { foreach (Property prop in props) { if (prop.getNotifyChange() && TFSMapper.getInstance().setEcrValues(newEcr, prop.getKey(), workItem)) { noOfMappedChanged++; } } } return(noOfMappedChanged); }
public static AttributesMapper getInstance() { if (instance == null) { instance = new AttributesMapper(); } return(instance); }
// Return if the workitem is updated (saved) by the handling code. public void handleEvent( Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem, String user, WorkItemChangedEvent notification) { Status status = new Status(); // If the user is the OSLC Provider functional user we will only update status // message if so needed. This as changes from the OSLC Provider originates from // external source = currently: MHWeb. Need revisit to allow multiple clients. String aboutStr = AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ABOUT, workItem); if (!user.Equals(HandlerSettings.TFSProviderUser, StringComparison.OrdinalIgnoreCase)) { if (aboutStr.Length == 0) { // We do not have a linked TR, we need to create createTR(workItem, notification, user, ref status); } else { Uri about = new Uri(aboutStr); Status statusAssign = null; EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_ASSIGN); TeamFoundationIdentity assignedTo = HandlerSettings.GetSignumForAssignedTo(workItem); if (user != null && assignedTo != null && !user.Equals(HandlerSettings.GetUserFromSignum(assignedTo.UniqueName), StringComparison.OrdinalIgnoreCase)) { statusAssign = new Status(); ecr.SetOwner(user); callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref statusAssign); } // We have a TR linked which might need to be updated updateTR(workItem, notification, user, about, ref status); if (statusAssign != null && statusAssign.OK) { ecr.SetOwner(HandlerSettings.GetUserFromSignum(assignedTo.UniqueName)); callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref statusAssign); } } } // Handle update of Bug ECRMapper.updateBug(status, user, workItem); }
// Return an EnterpriseChangeRequest with mapped values needed for the state transiton // If there is a fail with mapping some values, this will be captured in event log. // TODO: This could likely be described in a xml mapping file for configuration public static EnterpriseChangeRequest mapFromWorkitem( Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem, Uri about, String action) { EnterpriseChangeRequest newEcr = new EnterpriseChangeRequest(); newEcr.SetAbout(about); // Create a mapped ECR based on suggested action switch (action) { case ACTION_CREATE: newEcr.SetTitle(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_TITLE, workItem)); newEcr.SetDescription(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_DESCRIPTION, workItem)); newEcr.SetCurrentMho(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CURRENT_MHO, workItem)); newEcr.SetCustomer(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CUSTOMER, workItem)); newEcr.SetProduct(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_PRODUCT, workItem)); newEcr.SetProductRevision(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_PRODUCT_REVISION, workItem)); newEcr.SetNodeProduct(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_NODE_PRODUCT, workItem)); newEcr.SetNodeProductRevision(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_NODE_PRODUCT_REVISION, workItem)); // Note: The field firstTechnicalContact also is needed for TR creation. This we retrieve from // the user in the create notification, and put in the REST call header as required by MHWeb. // Formally we have mapping specified in ERICSSON_DEFECT_CREATOR_SIGNUM, but not used. // Add the connected Bug as related link Uri relatedBug = new Uri(HandlerSettings.GetUriForBug(workItem.Id.ToString())); String label = workItem.Id.ToString() + ": " + workItem.Title; OSLC4Net.Core.Model.Link link = new OSLC4Net.Core.Model.Link(relatedBug, label); newEcr.AddRelatedChangeRequest(link); break; case ACTION_REGISTER_ROUTE: newEcr.SetAction(ACTION_REGISTER_ROUTE); newEcr.SetImpactOnISP(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_IMPACT_ON_ISP, workItem)); newEcr.SetPriority(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_PRIORITY, workItem)); newEcr.SetDiddet(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_DIDDET, workItem)); newEcr.SetActivity(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ACTIVITY, workItem)); newEcr.SetFirstTechContactInfo(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_FIRST_TECHNICAL_CONTACT_INFO, workItem)); newEcr.SetCountry(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_COUNTRY, workItem)); newEcr.SetSite(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_SITE, workItem)); break; case ACTION_ASSIGN: newEcr.SetAction(ACTION_ASSIGN); newEcr.SetOwner(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_OWNER, workItem)); break; case ACTION_PROPOSE: newEcr.SetAction(ACTION_PROPOSE); newEcr.SetDiddet(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_DIDDET, workItem)); newEcr.SetActivity(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ACTIVITY, workItem)); newEcr.SetFirstTechContactInfo(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_FIRST_TECHNICAL_CONTACT_INFO, workItem)); newEcr.SetExpectedImpactOnISP(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_EXPECTED_IMPACT_ON_ISP, workItem)); newEcr.SetAnswer(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ANSWER, workItem)); newEcr.SetFaultCode(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_FAULTCODE, workItem)); newEcr.SetAnswerCode(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ANSWER_CODE, workItem)); // Corrected Product info is mandatory for some answerCodes and optional for others. Here // we pass in all cases and let the bug.xml handle mandatoryness and mhweb complain if not // present. newEcr.SetCorrectedProduct( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_PRODUCT, workItem)); newEcr.SetCorrectedProductRevision( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_PRODUCT_REVISION, workItem)); newEcr.SetCorrectedNodeProduct( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_NODE_PRODUCT, workItem)); newEcr.SetCorrectedNodeProductRevision( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_NODE_PRODUCT_REVISION, workItem)); break; case ACTION_APPROVE: newEcr.SetAction(ACTION_APPROVE); break; case ACTION_VERIFY: newEcr.SetAction(ACTION_VERIFY); newEcr.SetCorrectedNodeProduct( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_NODE_PRODUCT, workItem)); newEcr.SetCorrectedNodeProductRevision( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_NODE_PRODUCT_REVISION, workItem)); break; case ACTION_ANSWER: newEcr.SetAction(ACTION_ANSWER); newEcr.SetCorrectedNodeProduct( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_NODE_PRODUCT, workItem)); newEcr.SetCorrectedNodeProductRevision( AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_CORRECTED_NODE_PRODUCT_REVISION, workItem)); break; case ACTION_ACCEPT: newEcr.SetAction(ACTION_ACCEPT); break; case ACTION_REJECT: newEcr.SetAction(ACTION_REJECT); newEcr.SetNotebook(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_NOTEBOOK, workItem)); break; case ACTION_DUPLICATE: newEcr.SetAction(ACTION_DUPLICATE); newEcr.SetPrimaryTR(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_PRIMARYTR, workItem)); break; case ACTION_UNDUPLICATE: newEcr.SetAction(ACTION_UNDUPLICATE); break; case ACTION_CHANGE_PRODUCT: newEcr.SetAction(ACTION_CHANGE_PRODUCT); newEcr.SetProduct(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_PRODUCT, workItem)); newEcr.SetProductRevision(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_PRODUCT_REVISION, workItem)); newEcr.SetNodeProduct(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_NODE_PRODUCT, workItem)); newEcr.SetNodeProductRevision(AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_NODE_PRODUCT_REVISION, workItem)); break; case ACTION_REACTIVATE: newEcr.SetAction(ACTION_REACTIVATE); break; case ACTION_FINISH: newEcr.SetAction(ACTION_FINISH); break; case ACTION_DISCONNECT: newEcr.SetAction(ACTION_DISCONNECT); break; } return(newEcr); }
private static bool initMapping(XElement config, String adapterHome) { try { attributeMappingFile = config.Element("attributeMappingFile").Attribute("name").Value; attributeMappingFile = replaceRelativePath(adapterHome, attributeMappingFile); handleConfigFileChange(ConfigFile.ATTRIBUTE_MAPPINGS, attributeMappingFile); if (!File.Exists(attributeMappingFile)) { LogMessage( String.Format("Failed to find attribute mapping file at: {0}. Exit.", attributeMappingFile), LoggingLevel.ERROR); return(false); } else if (!AttributesMapper.getInstance().Load(attributeMappingFile, false)) { // Logging of error in Load method return(false); } LogMessage("Attribute mapping file read: " + attributeMappingFile, LoggingLevel.INFO); customerMappingFile = config.Element("customerMappingFile").Attribute("name").Value; customerMappingFile = replaceRelativePath(adapterHome, customerMappingFile); handleConfigFileChange(ConfigFile.CUSTOMER_MAPPINGS, customerMappingFile); if (!File.Exists(customerMappingFile)) { LogMessage( String.Format("Failed to find customer mapping file at: {0}. Exit.", customerMappingFile), LoggingLevel.ERROR); return(false); } else if (!AttributesMapper.getInstance().Load(customerMappingFile, true)) { // Logging of error in Load method return(false); } LogMessage("Customer mapping file read: " + customerMappingFile, LoggingLevel.INFO); productMappingFile = config.Element("productMappingFile").Attribute("name").Value; productMappingFile = replaceRelativePath(adapterHome, productMappingFile); handleConfigFileChange(ConfigFile.PRODUCT_MAPPINGS, productMappingFile); if (!File.Exists(productMappingFile)) { LogMessage( String.Format("Failed to find product mapping file at: {0}. Exit.", productMappingFile), LoggingLevel.ERROR); return(false); } else if (!ProductMapper.getInstance().Load(productMappingFile)) { // Logging of error in Load method return(false); } LogMessage("Product mapping file read: " + productMappingFile, LoggingLevel.INFO); } catch (Exception e) { LogMessage( String.Format("Exception when loading a mapping file: {0}. Exit.", e.Message), LoggingLevel.ERROR); return(false); } return(true); }
// Update the connected TR State. Return if the bug is updated or not. private void updateTRState( Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem, String oldState, String newState, String user, Uri about, ref Status status) { status.TRState = ECRMapper.getTRState(workItem); if (oldState.Equals(ECRMapper.BUG_STATE_ACTIVE, StringComparison.OrdinalIgnoreCase) && newState.Equals(ECRMapper.BUG_STATE_RESOLVED, StringComparison.OrdinalIgnoreCase)) { // UC 4: Updated TR based on the Bug's Active -> Resolve state change EnterpriseChangeRequest ecr = null; if (status.TRState.Equals(ECRMapper.TR_STATE_ASSIGNED)) { ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_PROPOSE); callUpdateTR(ecr, user, ECRMapper.TR_STATE_PROPOSED_S, ref status); if (!status.OK) { return; } } if (status.TRState.Equals(ECRMapper.TR_STATE_PROPOSED)) { String answerCode = ""; if (ecr != null) { answerCode = ecr.GetAnswerCode(); } else { answerCode = AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ANSWER_CODE, workItem); } if (answerCode.Contains("A") || answerCode.Contains("D") || answerCode.Contains("B11")) { // In case Answer Code = A*, D*, or B11 go directly to Answer callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_ANSWER), user, ECRMapper.TR_STATE_TECH_ANSW_PROV_S, ref status); return; } else { callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_APPROVE), user, ECRMapper.TR_STATE_PROP_APPROV_S, ref status); } } String expectedState = ECRMapper.TR_STATE_PROP_APPROV; if (!status.TRState.Equals(expectedState)) { // Incorrect pre condition HandlerSettings.LogMessage( String.Format("Expected TR State: {0}, current TR state: {1}", expectedState, status.TRState), HandlerSettings.LoggingLevel.WARN); } // Note: Here we assume we are in trState PA, as we accepted AS, PP and PA. If we have not failed // before, this is where we will fail if any assumption was wrong -> error message. if (status.OK) { callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_VERIFY), user, ECRMapper.TR_STATE_TECH_ANSW_PROV_S, ref status); } } else if (oldState.Equals(ECRMapper.BUG_STATE_RESOLVED, StringComparison.OrdinalIgnoreCase) && newState.Equals(ECRMapper.BUG_STATE_CLOSED, StringComparison.OrdinalIgnoreCase)) { // Update a TR based on Close of the Bug's Resolve -> Close state change String expectedState = ECRMapper.TR_STATE_TECH_ANSW_PROV; if (!status.TRState.Equals(expectedState)) { // Incorrect pre condition HandlerSettings.LogMessage( String.Format("Expected TR State: {0}, current TR state: {1}", expectedState, status.TRState), HandlerSettings.LoggingLevel.WARN); } // TODO: Put the condition in configuration file etc. String answerCode = AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ANSWER_CODE, workItem); if (answerCode.Equals("D4")) { // UC 9.3 - Bug set as Postponed callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_ACCEPT), user, ECRMapper.TR_STATE_POSTPONED_S, ref status); } else if (answerCode.Equals("Duplicate")) { // UC 9.4 - Bug set as Duplicate callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_DUPLICATE), user, null, ref status); } else { // UC 9.1 - Close of Bug from TFS callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_FINISH), user, ECRMapper.TR_STATE_FINISHED_S, ref status); } } else if (oldState.Equals(ECRMapper.BUG_STATE_RESOLVED, StringComparison.OrdinalIgnoreCase) && newState.Equals(ECRMapper.BUG_STATE_ACTIVE, StringComparison.OrdinalIgnoreCase)) { // UC 9.2: Update a TR based the Bug's Resolved -> Active state change callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_REJECT), user, ECRMapper.TR_STATE_REGISTERED_S, ref status); if (!status.OK) { return; } // If Bug is assigned to a user we need to drive change back to Assigned state EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_ASSIGN); if (ecr.GetOwner() != null && ecr.GetOwner().Length > 0) { callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref status); } } else if (oldState.Equals(ECRMapper.BUG_STATE_CLOSED, StringComparison.OrdinalIgnoreCase) && newState.Equals(ECRMapper.BUG_STATE_ACTIVE, StringComparison.OrdinalIgnoreCase)) { // UC 9.2: Update a TR based the Bug's Closed -> Active state change // In case of Closed -> Active, this is only allowed for the "no action" answer codes // in MHWeb, so OK for this to fail if selecting the incorrect answer code. // Could block in Bug.xml if we want to prevent some cases. callUpdateTR(ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_REACTIVATE), user, ECRMapper.TR_STATE_REGISTERED_S, ref status); if (!status.OK) { return; } // If Bug is assigned to a user we need to drive change back to Assigned state EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_ASSIGN); if (ecr.GetOwner() != null && ecr.GetOwner().Length > 0) { callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref status); } } else if (oldState.Equals(ECRMapper.BUG_STATE_ACTIVE, StringComparison.OrdinalIgnoreCase) && newState.Equals(ECRMapper.BUG_STATE_ACTIVE, StringComparison.OrdinalIgnoreCase)) { // UC 3 (one case): Handle Assign case - state change for TR, attribute change for Bug // Incorrect pre condition String expectedState = ECRMapper.TR_STATE_REGISTERED; if (!status.TRState.Equals(expectedState)) { HandlerSettings.LogMessage( String.Format("Expected TR State: {0}, current TR state: {1}", expectedState, status.TRState), HandlerSettings.LoggingLevel.WARN); } // Handle case when we are in state PR if (status.TRState.Equals(ECRMapper.TR_STATE_PRIVATE)) { callUpdateTR(ECRMapper.mapFromWorkitem( workItem, about, ECRMapper.ACTION_REGISTER_ROUTE), user, ECRMapper.TR_STATE_REGISTERED_S, ref status); } callUpdateTR(ECRMapper.mapFromWorkitem( workItem, about, ECRMapper.ACTION_ASSIGN), user, ECRMapper.TR_STATE_ASSIGNED_S, ref status); } }