Forums

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

How to retrieve more information from a Jira Structure by Scriptrunner?

ABoerio
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 10, 2019

Hi,

our projects (industrial R&D, non software) are led with hybrid approach. High level plan and some wbs elements follow waterfall approach, while for some wbs sub elements kanban or scrum is perfect. Due to this, we're working very well with Jira + Structure by Alm Works (Great product).

I need to retrieve information from a Structure using Scriptrunner (to generate specific reports, compile Confluence Pages, etc...). I'm actually learning java and groovy step by step, so pretty sure my scripts are full of non elegant lines ... :-)

So far I've been able to get some basic fields, but I need to get what in Structure is called the Sequential Index. It looks like this field cannot be retrieved directly, or I'm looking in the wrong place in the API reference. Has to be built within the script? Any suggestions?

Below the code I wrote so far. It generates a very simple table (that later on I'll send to a confluence page as I already do with other scripts). At the moment the Sequential Index colunm is empty, as I've not been able to fill it correctly yet. Apart from this it works.


//Name of the structure
String structureName="MARTHA"

//generic import
import groovy.xml.MarkupBuilder

//Structure import
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.almworks.jira.structure.api.structure.StructureManager
import com.almworks.jira.structure.api.permissions.PermissionLevel
import com.almworks.jira.structure.api.forest.ForestSpec
import com.almworks.jira.structure.api.row.StructureRow
import com.almworks.jira.structure.api.row.RowManager
import com.almworks.jira.structure.api.structure.Structure
import com.almworks.jira.structure.api.StructureComponents
import com.almworks.jira.structure.api.item.ItemIdentity
import com.almworks.jira.structure.api.item.CoreIdentities
import com.almworks.jira.structure.api.attribute.StructureAttributeService
import com.almworks.jira.structure.api.attribute.CoreAttributeSpecs
import com.almworks.jira.structure.api.attribute.VersionedRowValues
import com.almworks.integers.LongArray
import com.almworks.integers.LongIterator
//Needed notes for Structure
@WithPlugin("com.almworks.jira.structure")
@PluginModule
StructureComponents sc

//Objects to handle structure
StructureManager sm = sc.getStructureManager()
RowManager rowManager = sc.getRowManager()
def forestService = sc.getForestService()

//Permission to access the structure
def permission = PermissionLevel.valueOf("ADMIN")

//Definition
//Structure
def struct = sm.getStructuresByName(structureName, permission)[0]
//Forest Specification
def forestSpec = ForestSpec.structure(struct.getId())
//Forest Source
def forestsrc=forestService.getForestSource(forestSpec)
//Forest - Last version
def forest = forestSrc.getLatest().getForest()
//Forest rows
def forestRows=forest.getRows()

//Attribute list to be read later on
List attributeSet = new ArrayList<>()
attributeSet.add(CoreAttributeSpecs.KEY)
attributeSet.add(CoreAttributeSpecs.SUMMARY)
//attributeSet.add(CoreAttributeSpecs.TOTAL_REMAINING_ESTIMATE);

//Match rows with attributes
VersionedRowValues values = sc.getAttributeService().getAttributeValues(forestSpec, forestRows, attributeSet);


//Start building report
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)


//heading before table
xml.p{
h3("Riepilogo Struttura" + structureName)
h4("")
}

//building table
xml.table(class: "aui") {

thead {
tr {
//column headers
th("#")
th("Sequential Index")
th("Type")
th("Key")
th("Summary")
}
}

// counter
int rowNumber=0

tbody{

//iteration through structure rows
for (LongIterator ri : forestRows) {
StructureRow row = rowManager.getRow(ri.value())
rowNumber=rowNumber+1
//Identify item in the row
ItemIdentity itemId = row.getItemId()

tr{

//In case of an issue
if (CoreIdentities.isIssue(itemId)){
td(String.valueOf(rowNumber))
td("")
td("Issue")
td(values.get(ri.value(), CoreAttributeSpecs.KEY))
td(values.get(ri.value(), CoreAttributeSpecs.SUMMARY))
}
//In case of other (folders mainly)
else{
td(String.valueOf(rowNumber))
td("")
td("Non Issue")
td("")
td(values.get(ri.value(), CoreAttributeSpecs.SUMMARY))

}
}

}
}
}


//Output nel Result di Scriptrunner

return writer.toString()

 

Thanks in advance for any hint.

Andrea-

 

 

1 answer

1 accepted

1 vote
Answer accepted
ABoerio
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 18, 2019

Problem solved with the direct support of https://almworks.com/

Actually it is possible to retrieve the Sequential Index, using the following

//This is the specific line needed to retrieve the Sequential Index
AttributeSpec sequentialIndex = new AttributeSpec<>("seq", ValueFormat.TEXT)
attributeSet.add(sequentialIndex)


The fact that you need to use the string "seq" was not very well documented in the Structure API, I'd say, but I must admit that with a direct support call I got all the information I needed. 

Great support.

Here below the full working code that I'll then further develop to generate the reports I need.

//Retrieve information from a Jira Structure

//Name of the Structure to call
String structureName="NICE"

//Generic import
import groovy.xml.MarkupBuilder

//Specific import for Jira Structure
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.almworks.jira.structure.api.structure.StructureManager
import com.almworks.jira.structure.api.permissions.PermissionLevel
import com.almworks.jira.structure.api.forest.ForestSpec
import com.almworks.jira.structure.api.row.StructureRow
import com.almworks.jira.structure.api.row.RowManager
import com.almworks.jira.structure.api.structure.Structure
import com.almworks.jira.structure.api.StructureComponents
import com.almworks.jira.structure.api.item.ItemIdentity
import com.almworks.jira.structure.api.item.CoreIdentities
import com.almworks.jira.structure.api.attribute.StructureAttributeService
import com.almworks.jira.structure.api.attribute.CoreAttributeSpecs
import com.almworks.jira.structure.api.attribute.AttributeSpec
import com.almworks.jira.structure.api.attribute.AttributeSpecBuilder
import com.almworks.jira.structure.api.attribute.ValueFormat
import com.almworks.jira.structure.api.attribute.VersionedRowValues
import com.almworks.integers.LongArray
import com.almworks.integers.LongIterator

//Also necessary for Jira Structure
@WithPlugin("com.almworks.jira.structure")
@PluginModule
StructureComponents sc

//Structure handlers
StructureManager sm = sc.getStructureManager()
RowManager rowManager = sc.getRowManager()
def forestService = sc.getForestService()

//Permission access to structure
def permission = PermissionLevel.valueOf("ADMIN")

//Get Structure
def struct = sm.getStructuresByName(structureName, permission)[0]
//Forest Specification
def forestSpec = ForestSpec.structure(struct.getId())
//Forest Source
def forestsrc=forestService.getForestSource(forestSpec)
//Forest - Last version
def forest = forestSrc.getLatest().getForest()
//Forest Rows
def forestRows=forest.getRows()

//List of attributes to be retrieved and then used somewhere
List attributeSet = new ArrayList<>()
attributeSet.add(CoreAttributeSpecs.KEY)
attributeSet.add(CoreAttributeSpecs.SUMMARY)
//This is the specific line needed to retrieve the Sequential Index
AttributeSpec sequentialIndex = new AttributeSpec<>("seq", ValueFormat.TEXT)
attributeSet.add(sequentialIndex)

//Build a matrix that relates forest rows with the attributes chosen before
VersionedRowValues values = sc.getAttributeService().getAttributeValues(forestSpec, forestRows, attributeSet);


//Def writer and xml to build output
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)

//Heading prior to the table
xml.p{
h3("Riepilogo Struttura: " + structureName)
h4("")
}

//Build table
xml.table(class: "aui") {

thead {
tr {
//Columns
th("#")
th("Seq.Index")
th("Type")
th("Key")
th("Summary")
}
}

// Row counter
int rowNumber=0

tbody{

//Iterate among forest rows
for (LongIterator ri : forestRows) {
//Get the specific row
StructureRow row = rowManager.getRow(ri.value())
rowNumber=rowNumber+1
//Identify type of item in the row
ItemIdentity itemId = row.getItemId()

tr{

//In case of an Issue
if (CoreIdentities.isIssue(itemId)){
//Compile row cells
td(String.valueOf(rowNumber))
td(values.get(ri.value(), sequentialIndex))
td("Issue")
td(values.get(ri.value(), CoreAttributeSpecs.KEY))
td(values.get(ri.value(), CoreAttributeSpecs.SUMMARY))
}
//In case of another item "(normally folders)"
else{
//Compile row cells
td(String.valueOf(rowNumber))
td(values.get(ri.value(), sequentialIndex))
td("Non Issue")
td("")
td(){b(values.get(ri.value(), CoreAttributeSpecs.SUMMARY))}

}
}

}
}
}


//Evaluate output in Scriptrunner console
return writer.toString()

 

Ciao, Andrea

Suggest an answer

Log in or Sign up to answer