dannyman.toldme.com


JIRA

JIRA Cascading Select in Jython

The Cascading Select Custom Field type in JIRA is a bear. The first trick is learning to set the “null” value and then the “1” child value. The next trick is building out a ModifiedValue object to hold your change. Then you get to jump down the rabbit hole of finding the correct Option values for the custom field, and setting them with the tricks just mentioned.

So, in the interests of saving me sanity next time I need to set a Cascading Select, here’s a Jython function that works in Jira 4.2:

import logging
 
from com.atlassian.jira import ComponentManager
from com.atlassian.jira.issue.customfields.manager import OptionsManager
from com.atlassian.jira.issue.customfields.view import CustomFieldParamsImpl
from com.atlassian.jira.issue import ModifiedValue
from com.atlassian.jira.issue.util import DefaultIssueChangeHolder
from java.util import HashSet
 
# cf = custom field
# issue = issue to modify
# parent = top value to set (string value)
# child = child value to set (string value)
def set_cascading_select(cf, issue, parent, child):
    # Get the managers
    cfm = ComponentManager.getInstance().getCustomFieldManager()
    om = ComponentManager.getComponentInstanceOfType(OptionsManager)
    fli = ComponentManager.getInstance().getFieldLayoutManager().getFieldLayout(issue).getFieldLayoutItem(cf)
 
    parent_options = om.getOptions(cf.getRelevantConfig(issue))
    parent_option = None
    child_option = None
    try:
        parent_option = parent_options.getOptionForValue(parent, None)
    except:
        pass
    try:
        child_option = parent_options.getOptionForValue(child, parent_option.getOptionId())
    except:
        pass
 
    if parent_option and child_option:
        old_application = issue.getCustomFieldValue(cf)
        new_application = CustomFieldParamsImpl(cf)
        a_none = HashSet()
        a_none.add(parent_option)
        a_1 = HashSet()
        a_1.add(child_option)
        new_application.put(None, a_none)
        new_application.put("1", a_1)
        mf = ModifiedValue(old_application, new_application)
        cf.updateValue(fli, issue, mf, DefaultIssueChangeHolder())
        logging.debug("set issue " + issue.getKey() + " cf " + cf.getName() + " setting " + parent + "/" + child)
        return True
    else:
        logging.error("invalid parent/child option: " + parent + "/" + child)
        return None

Example function calls from within a validation hook:

cfm = ComponentManager.getInstance().getCustomFieldManager()
 
application_cf = cfm.getCustomFieldObjectByName("Beverages")
 
# good
set_cascading_select(application_cf, issue, "Hard Drinks", "Whiskey")
# bad child
set_cascading_select(application_cf, issue, "Hard Drinks", "Coke")
# bad parent
set_cascading_select(application_cf, issue, "Soft Drinks", "Whiskey")
# total crap
set_cascading_select(application_cf, issue, "Illicit Drugs", "Bath Salts")

The logging stuff is useful for debugging, if you have that set up, else just remove those bits.

Read More

Next:
Previous:
Categories: JIRA