Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Listener is Not Working when issue is cancelled status

J Manas Kumar
Contributor
April 14, 2020

HI 

 

I have a requirement like when a story is linked with an Epic , a custom field value will be added to epic's custom field. so when my User Story is transition from open to cancelled Status those value should be also removed from Epic's Custom Field.

My problem is when i am moving my Story to Cancelled Status this code is not working.

I am printing issue status in log, its showing "OPEN", even if issue is in "CANCELLED" status.

Any help will be appreciated.

 

import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.customfields.option.Option

import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.bc.issue.search.SearchService

import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter

import org.apache.log4j.Logger

def log = Logger.getLogger("com.citi.jira.listener.Listener")

log.setLevel(org.apache.log4j.Level.DEBUG)

Issue mainIssue = event.issue
String issuetype = mainIssue.getIssueType().getName()


if(issuetype == "Story"){
log.debug("My New Listener for Story Cancellation")
String eventType = event.getEventTypeId() as String
//eventType == "13"
String status = mainIssue.getStatus().getName()
log.debug("Status For My Story" + status)
log.debug("whats the event here? :--" + event)
if(status == "Cancelled"){


log.debug("Entering Into Cancelled State for after story got Cancelled")
log.debug("Looks it it was workflow change")
log.debug("Issue is: "+event.issue)
Issue issue = event.issue as Issue

 

if (event?.getChangeLog()?.getRelated("ChildChangeItem")?.find { it.field == "Impacted Application/s" }) {

log.debug("We are in Imapcted Application event change scenario for U.S")
def customFieldManager = ComponentAccessor.getCustomFieldManager()

def epicLinkField = customFieldManager.getCustomFieldObjects(event.issue).find {it.name == "Epic Link"}
def epicLinkValue = mainIssue.getCustomFieldValue(epicLinkField)
log.debug("Epic Link Value is: "+epicLinkValue)

boolean needToUpdate = false

if(epicLinkValue != null){
log.debug("Epic Link Value is not NULL: "+epicLinkValue+ " We are in the epicLink is not Empty case!")

def issueManager = ComponentAccessor.getIssueManager()
def userManager = ComponentAccessor.getUserManager()
ApplicationUser admin = userManager.getUserByName("INT_JIRA")
Issue ParentIssue = issueManager.getIssueObject(""+epicLinkValue)

log.debug("The Epic of this User Story is: "+ParentIssue.getKey())

def changeItem = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find { it.field == "Impacted Application/s" }
String[] newValue = changeItem.get("newstring").toString().split(';')
String[] oldValue = changeItem.get("oldstring").toString().split(';')

//Remove leading and trialing white spaces from every entry in New Value/Old Value Array
newValue = removeWhiteSpacesInArrayElements( newValue )
oldValue = removeWhiteSpacesInArrayElements( oldValue )
CustomField impactedAppField = customFieldManager.getCustomFieldObjects(ParentIssue).find {it.name == "Impacted Application/s"}

log.debug("The Epic of this User Story is: "+ParentIssue.getKey())

String epicImpactedFieldValue = ParentIssue.getCustomFieldValue(impactedAppField) as String
if(epicImpactedFieldValue != null){

log.debug("New Value: "+newValue)
log.debug("Old Value: "+oldValue)

if(newValue[0] == 'null') newValue = []
if(oldValue[0] == 'null') oldValue = []

log.debug("The Removals are: "+ determineRemoval(oldValue, newValue))

ArrayList<String> Removal = determineRemoval(oldValue, newValue)
String newAppList = ""


if(Removal.isEmpty() == false){
log.debug("We are in Removal scenario")

//Check if CSI removed is unique to US
log.debug("We need to loop through "+Removal)
ArrayList<String> uniqueAppId = generateUniqueImpactedAppUnderParent(mainIssue, ParentIssue, Removal, admin)

log.debug("Unique values from removal is: "+uniqueAppId)

if(uniqueAppId.isEmpty() == false) {

needToUpdate = true
log.debug("Updated needtoUpdate flag to: "+needToUpdate)
log.debug("Unique App Id array is not em,pty which means that we had unique values removed from U.S")
//This means that we had 0 additions this time around
if(newAppList == ""){
log.debug("New App List string is empty which means there was nothing added to User Story to add to EPic.")

//Ensure the Impacted App Array has NO leading or trailing blank spaces.
String[] epicImpactedFieldArray = epicImpactedFieldValue.split(';')
epicImpactedFieldArray = removeWhiteSpacesInArrayElements( epicImpactedFieldArray)

log.debug("Values in Epic Impacted App field is: "+epicImpactedFieldArray)

newAppList = ""
for (String name : epicImpactedFieldArray) {
newAppList += name.trim() +";"
}
newAppList = newAppList.substring(0,newAppList.length()-1)
epicImpactedFieldArray = newAppList.split(";")
log.debug("PRInting New App List : ----- "+newAppList)
log.debug("Values in Epic Impacted App after temp is: "+epicImpactedFieldArray)

//Need to rmemove teh unique ones at Epic level I have determined from US
String[] cleansedEpic = cleanseList(epicImpactedFieldArray, uniqueAppId)
log.debug("New values at epic level after remvoing unique is: "+ cleansedEpic)


// Added By Manas
// here i have added the loop because when ever the value is null its will check for Null, if NewAppList nUll it will default set
// the value of newAppList to null
// else it will go to else block to follow the regular structure and print the rest CSi values which will print other csi values
if(cleansedEpic.size() == 0 || cleansedEpic.size() == []){

log.debug("Printing newAppList Length() ---: "+newAppList.length())
log.debug("Printing Size of cleansedEpic ---: "+cleansedEpic.size())
newAppList = ""
modifyValue(admin,ParentIssue,impactedAppField, newAppList )
}else{

newAppList = convertStringArraytoApplication(cleansedEpic)
log.debug("Value we are adding at Epic level is: "+newAppList)

modifyValue(admin,ParentIssue,impactedAppField, newAppList )
}

}
//THis means we had addition done already
else {

log.debug("New APp List Sting is NOT empty which means we have things to add to Epic adn we need to delete accordingly")
//Ensure the Impacted App Array has NO leading or trailing blank spaces.

String[] epicImpactedFieldArray = newAppList.split(";")
epicImpactedFieldArray = removeWhiteSpacesInArrayElements( epicImpactedFieldArray)
log.debug("Value found in AppList after splitting into Array : "+epicImpactedFieldArray)

//Need to rmemove teh unique ones at Epic level I have determined from US
String[] cleansedEpic = cleanseList(epicImpactedFieldArray, uniqueAppId)
log.debug("New values at epic level after remvoing unique is: "+ cleansedEpic)

newAppList = convertStringArraytoApplication(cleansedEpic)
log.debug("Value we are adding at Epic level is: "+newAppList)

}
} else log.debug("There was NO unique values in REMOVASarray from Story")
} else {

log.debug("Removal array is e,pty and has no entries therefore we do n othing since wee do not have an addition scernario")
}

}

}


}else{

}
}
}

 

String[] removeWhiteSpacesInArrayElements(String[] arr){

String[] newAppList = arr
def counter = 0
for (String name : arr) {

newAppList[counter] = (name.trim())
counter++
}
return newAppList

}

//Returns: ALL the unique Impacted app that a given child issue has relating to its Parent Issue
ArrayList<String> generateUniqueImpactedAppUnderParent(Issue childIssue, Issue parentIssue, ArrayList<String> impactedAppToCheck, ApplicationUser admin){

def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class)
def searchService = ComponentAccessor.getComponent(SearchService)

ArrayList<String> uniqueAppId = new ArrayList<>()
for (String appId : impactedAppToCheck) {

appId = appId.trim()
log.debug("My User Story is: "+childIssue.getKey())
log.debug("We are looping through: "+ appId)
def query1 = "'Epic Link' = '" + parentIssue.getKey() +"' AND issuetype = Story AND 'Impacted Application/s' ~ '"+appId +"'"
SearchService.ParseResult parseResult1 = searchService.parseQuery(admin, query1)
def result1 = searchService.search(admin, parseResult1.getQuery(), PagerFilter.getUnlimitedFilter())
def results = result1.getTotal()

//If we have more tehn 1 result that means its not unique. If we have 1 it is UNIQUE
log.debug("Total amount of results is: "+results)
if(result1.getTotal() == 0) uniqueAppId.add(appId)

}

return uniqueAppId
}

//Desc: Method checks if values in Arr2 exist in arr1
//Return: A combined but unique array from the addition of arr1 and arr2
String[] determineUniqueValues(String[] arr1, String[] arr2){

arr1 = removeWhiteSpacesInArrayElements(arr1)
arr2 = removeWhiteSpacesInArrayElements(arr2)
String[] combinedImpactedAppArray = arr1
combinedImpactedAppArray = combinedImpactedAppArray += arr2

log.debug("Value found at Epic level is: "+arr1)
log.debug("User Story Impacted App field value is: "+arr2)
log.debug("Combined Array of Epic and U.S is: "+combinedImpactedAppArray)

String[] uniqueCombinedImpactedAppArray = combinedImpactedAppArray.toUnique()
log.debug("Unique values in combinedImpactedArray are: "+ uniqueCombinedImpactedAppArray)

log.debug("Unique size is: "+uniqueCombinedImpactedAppArray.size())
log.debug("Epic original size is: "+arr1.size())

return uniqueCombinedImpactedAppArray

}
String convertStringArraytoApplication(String[] newValue) {
String newAppList = ""
for (String name : newValue) {

newAppList += name.trim() +"; "
}
return newAppList.substring(0,newAppList.length()-2)

}
//Return: Determine things in newValue that do not exist in oldValue
String[] cleanseList(String[] listToCleanse, ArrayList<String> cleanseCriteria) {

HashSet<String> toCleanseSet = new HashSet<String>(Arrays.asList(listToCleanse))
ArrayList<String> toCleanseList = new ArrayList<>(toCleanseSet)

toCleanseList.removeAll(cleanseCriteria)
return toCleanseList as String[]

}

//Return: Determine things in newValue that do not exist in oldValue
ArrayList<String> determineAdditions(String[] oldValue, String[] newValue) {

//String[] result = []
HashSet<String> old = new HashSet<String>(Arrays.asList(oldValue))
ArrayList<String> oldArray = new ArrayList<>(old)
HashSet<String> newV = new HashSet<String>(Arrays.asList(newValue))
ArrayList<String> newArray = new ArrayList<>(newV)

newArray.removeAll(oldArray)

return newArray

}

//Return: Determine things in newValue that do not exist in oldValue
ArrayList<String> determineRemoval(String[] oldValue, String[] newValue) {

//String[] result = []
HashSet<String> old = new HashSet<String>(Arrays.asList(oldValue))
ArrayList<String> oldArray = new ArrayList<>(old)
HashSet<String> newV = new HashSet<String>(Arrays.asList(newValue))
ArrayList<String> newArray = new ArrayList<>(newV)

oldArray.removeAll(newArray)


//User could have deleted 1 item and added a new one. To truly know if it was addition or removal I need to
//
return oldArray

}

boolean modifyValue(ApplicationUser user, Issue issue, CustomField customField, String value){

IssueService issueService = ComponentAccessor.getComponent(IssueService);
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.addCustomFieldValue(customField.id, value)
def update = issueService.validateUpdate(user, issue.getId(), issueInputParameters)

/* validate update info and execute update */

if (update.isValid()) {

IssueService.IssueResult status = issueService.update(user, update)
if (!status.isValid())
{
for (def error : status) {

}
} else {

}
} else {


IssueService.IssueResult status = issueService.update(user, update)

for (def error : status) {

}
}

return true
}

 

 

 

 

Regards

Manas

0 answers

Suggest an answer

Log in or Sign up to answer