How can I add or remove a option to/form the todolist via a groovy script



  we are evaluating the todo addon and we need to add/remove entries to a TODO list for a specific issue programmatically (using groovy scripts). Can this be done?  Are ther code samples available?


Jan van de Klok 

1 answer


I have a customer that did programmatically change the status of a Checklist item using Script Runner. You need to get the customfield values from the issues. It will return  a ChecklistItem object. You get the string value of this object by calling getvalue, modify the metadata in the string, recreate the ChecklistItem and update the customfield with the new ChecklistItem. There is some metadata at the beginning of the checklist item in the form O-1-M or V1-1-M. The first part indicates if it is an Option or a Value entered at the issue level. The next field is 1 if item is checked, 0 otherwise. The last part, the M indicates that the item is mandatory. You can have some more examples by looking at the HTML values when browsing an issue.

As for an example, this is what the customer sent me when he got it working:

import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Category
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def issueService = ComponentAccessor.getIssueService();
def authContext = ComponentAccessor.getJiraAuthenticationContext();
def log = Category.getInstance('com.onresolve.jira.groovy.PostFunction');
def field = customFieldManager.getCustomFieldObjectByName("Acceptance Criteria");
def newOptions = [];
field.getValue(issue).each {
    oldValue = it.getValue().split('-');
    oldValue[1] = '0';
    newOptions << oldValue.join('-');
def user = authContext.getUser().getDirectoryUser();
def issueParams = issueService.newIssueInputParameters();
issueParams.addCustomFieldValue(field.getIdAsLong(), *newOptions);
validationResults = issueService.validateUpdate(user, issue.getId(), issueParams);
issueService.update(user, validationResults);

And here`s the ChecklistItem class which is returned by the customfield:

package com.okapya.jira.customfields;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.atlassian.jira.issue.customfields.option.Option;

public class ChecklistItem implements Comparable<ChecklistItem> {
    private Boolean checked = false;
    private String name;
    private String inputString;
    private Boolean disabled = false;
    private Integer index = 1;
    private Long optionId = 0L;

    public ChecklistItem() {

    public ChecklistItem(String initializationString) {
        if (!containsValidToken(initializationString)) {
            throw new IllegalArgumentException("Does not contain a valid initialization token.");
        inputString = initializationString;
        if (isOption()) {
            try {
                optionId = Long.valueOf(getName());
            } catch (NumberFormatException e) {
                // Ignore

    public ChecklistItem(Option option, Boolean checked, Boolean mandatory) {
        if (option == null)
            throw new IllegalArgumentException("Option parameter cannot be null.");

        name = option.getValue();
        this.checked = checked;
        disabled = option.getDisabled();
        optionId = option.getOptionId();
        String checkedCode = (checked) ? "1" : "0";
        String mandatoryCode = (mandatory) ? "-M" : "";
        inputString = "[O-" + checkedCode + mandatoryCode + "]" + option.getOptionId().toString();

    private void extractInfoFromToken(String inputString) {
        Pattern pattern = Pattern.compile("^\\[(O|V\\d{1,3}|V)-[01](-M)?\\]");
        Matcher matcher = pattern.matcher(inputString);
        String token;
        if (matcher.find()) {
            token =;
            name = inputString.substring(token.length());

            if (token.matches(".*-M\\]")) {
                // removes 2 chars for -M
                token = token.substring(0, token.length() - 2);

            checked = token.charAt(token.length() - 2) == '1';

            if (token.matches("^\\[V.*")) {
                pattern = Pattern.compile("\\d{1,3}");
                matcher = pattern.matcher(token);
                if (matcher.find()) {
                    index = Integer.parseInt(;

    public static Boolean containsValidToken(String value) {
        return value.matches("^\\[(O|V\\d{1,3}|V)-[01](-M)?\\].*");

    public Boolean isChecked() {
        return checked;

    public String getName() {
        return name;

    public String getValue() {
        return getSerializedString();

    public Integer getValueIndex() {
        return index;

    public Boolean isOption() {
        return inputString.matches("\\[O-[01](-M)?\\].*");

    public Boolean isDisabled() {
        return disabled;

    public Boolean isMandatory() {
        return inputString.matches("\\[.*-M\\].*");

    public String getSerializedString() {
        return inputString;

    public Long getOptionId() {
        return optionId;

    public boolean equals(Object item) {
        if (!(item instanceof ChecklistItem))
            return false;
        ChecklistItem checklistItem = (ChecklistItem) item;

        if (this.getSerializedString().equals(checklistItem.getSerializedString())) {
            return true;
        } else {
            return false;

    public int compareTo(ChecklistItem item) {
        return getValueIndex().compareTo(item.getValueIndex());
    public String toString() {
        return getName();

Suggest an answer

Log in or Sign up to answer
Atlassian Community Anniversary

Happy Anniversary, Atlassian Community!

This community is celebrating its one-year anniversary and Atlassian co-founder Mike Cannon-Brookes has all the feels.

Read more
Community showcase
Bridget Sauer
Published Thursday in Marketplace Apps

Calling all developers––You're invited to Atlas Camp 2018

 Atlas Camp   is our developer event which will take place in Barcelona, Spain  from the 6th -7th of   September . This is a great opportunity to meet other developers and get n...

361 views 0 6
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you