Sort list of linked issues returned from IssueLinkManager

Greg Bailey June 30, 2021

Hello,

I'm creating a Scriptrunner scripted field to list all linked issues of a certain type.

I have no problem getting the linked issues however I'm looking to sort the issue list by a specific field value and it looks to come back sorted by keys.  How can I sort the returned list by a given field?

Im currently getting the list of linked issues using the issuelinkmanager.  Is it possible to sort the returned list based on a certain issue field, like perhaps Sprint?


List<IssueLink> allOutIssueLink = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId());

 

1 answer

0 votes
Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
June 30, 2021

You can use the groovy sort method on any collection using a closure

import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.pyxis.greenhopper.jira")
import com.atlassian.greenhopper.customfield.sprint.SprintCFType
import com.atlassian.greenhopper.service.sprint.Sprint

List<IssueLink> allOutIssueLink = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId());

def sprintCf = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName('Sprint').find{it.customFieldType instanceof SprintCFType}
def sortedIssueLinks = allOutIssueLin.sort{linkedIssue->
(linkedIssue.getCustomFieldValue(sprintCf) as ArrayList<Sprint>).last().startDate
}

 This should sort by the Sprint start date of the last Sprint each issues are associated with (in case they have multiple sprints ... my experience is that the last sprint is generally the active one)

Greg Bailey June 30, 2021

I will definitely give that a try first thing in the morning here and report back.

Thanks so much Peter!

Greg Bailey July 6, 2021

Apologies for the delay, the holiday weekend started a bit early. ;-)

So trying this Im getting the error:

'Cannot find matching method com.atlassian.jira.issue.link.IssueLink#getCustomFieldValue'

for the '(linkedIssue.getCustomFieldValue(sprintCf) as ArrayList<Sprint>).last().startDate
}' line.

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import java.time.format.DateTimeFormatter
import com.atlassian.greenhopper.service.sprint.*;
import com.atlassian.jira.project.version.Version

import com.onresolve.scriptrunner.runner.customisers.WithPlugin
@WithPlugin("com.pyxis.greenhopper.jira")
import com.atlassian.greenhopper.customfield.sprint.SprintCFType
import com.atlassian.greenhopper.service.sprint.Sprint
IssueLinkTypeManager issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager

List<IssueLink> allOutIssueLink = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId());

def sprintCf = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName('Sprint').find{it.customFieldType instanceof SprintCFType}
def sortedIssueLinks = allOutIssueLink.sort{linkedIssue->
(linkedIssue.getCustomFieldValue(sprintCf) as ArrayList<Sprint>).last().startDate // <-- ERROR HERE
}
Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 6, 2021

Sorry... my bad. I obviously didn't test it before posting.

You just need to get the destination issue object before getting the sprint field value.

Replace that failing line with:

(linkedIssue.destinationObject.getCustomFieldValue(sprintCf) as ArrayList<Sprint>).last().startDate

 

Greg Bailey July 6, 2021

hmm changed to:

List<IssueLink> allOutIssueLink = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId());

def sprintCf = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName('Sprint').find{it.customFieldType instanceof SprintCFType}

def sortedIssueLinks = allOutIssueLink.sort{linkedIssue->
(linkedIssue.destinationObject.getCustomFieldValue(sprintCf) as ArrayList<Sprint>).last().startDate
}

And now get this error:

java.lang.UnsupportedOperationException at com.google.common.collect.ImmutableList.sort(ImmutableList.java:560) at Script277.run(Script277.groovy:43) 

 

Sorry to be such a pain, but this one has my stumped.

And note when we get this working I'll have a few different instances of this code sorting on various custom fields. I used sprint as an example.  one instance will be sorting on a custom date field.  

Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 6, 2021

It appears that LinkedIssue list is statically typed to a an List (java) rather than a Collection (groovy), so the groovy collection methods are not supported.

So the solution is to transform the linkedIssue list into a goovy collection and then sort that:

def allOutIssues = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId()).collect{it.destinationObject};

def sprintCf = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName('Sprint').find{it.customFieldType instanceof SprintCFType}

def sortedIssues = allOutIssues.sort{linkedIssue->
def sprints = linkedIssue.getCustomFieldValue(sprintCf) as ArrayList<Sprint>;
if(sprints){
log.info "start: ${sprints.last().startDate}"
return sprints.last().startDate
}
log.info "created $linkedIssue.created"
return linkedIssue.created
}

I added some protection in case some of the linked issues are not associated with any sprint.

Suggest an answer

Log in or Sign up to answer