Snippets
Created by
Francis Martens
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | package com.idalko.custom
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.issue.IssueEventManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.user.ApplicationUser
import com.idalko.jira.groovy.FieldValueUtil
import org.apache.log4j.Logger
import java.text.SimpleDateFormat
class ApprovalLogic {
private static Logger log = Logger.getLogger("com.idalko.plugins.custom.ApprovalLogic");
private static final String REVIEW_PROCESS_MARKER = "\n----\n";
// access all customfields in use for the approval logic
private static FieldValueUtil fvuToApprove = new FieldValueUtil("To approve");
private static FieldValueUtil fvuApprovers = new FieldValueUtil("Approvers");
private static FieldValueUtil fvuHasAccepted = new FieldValueUtil("Has accepted");
private static FieldValueUtil fvuHasDeclined = new FieldValueUtil("Has declined");
private static FieldValueUtil fvuDelegateTo = new FieldValueUtil("Delegate to");
private static FieldValueUtil fvuDelegateToEmail = new FieldValueUtil("ZZdte");
private static FieldValueUtil fvuApprovalComment = new FieldValueUtil("Approval comment");
private static JiraAuthenticationContext jac = ComponentAccessor.getJiraAuthenticationContext();
/**
* Remove the current user from the list of 'To approve'
* Remove the current user from the list of 'Has approved'
* Add the current user to the list of 'Has declined'
*
* Add his comment to the 'Approval comment'
*
* @param issue
*/
public static void doDecline(Issue issue, String comment) {
ApplicationUser currentUser = jac.getUser();
removeUser(fvuToApprove, issue, currentUser);
removeUser(fvuHasAccepted, issue, currentUser);
addUser(fvuHasDeclined, issue, currentUser);
addComment(issue, currentUser, "declined", comment);
FieldValueUtil.persistIssueModifications(issue, currentUser.getName());
}
/**
* Remove the current user from the list of 'To approve'
* Remove the current user from the list of 'Has declined'
* Add the current user to the list of 'Has accepted'
* Add his comment to the 'Approval comment'
*
* @param issue
*/
public static void doAccept(Issue issue, String comment) {
ApplicationUser currentUser = jac.getUser();
removeUser(fvuToApprove, issue, currentUser);
removeUser(fvuHasDeclined, issue, currentUser);
addUser(fvuHasAccepted, issue, currentUser);
addComment(issue, currentUser, "accepted", comment);
FieldValueUtil.persistIssueModifications(issue, currentUser.getName());
}
/**
* Delegate function will remove the currentuser from the toApprove and add
* the users contained in the 'Delegate to' custom field if not yet there
*
*/
public static void delegateTo(MutableIssue issue, String comment) {
String delegateNames = "";
String sep = "";
ApplicationUser currentUser = jac.getUser();
List<ApplicationUser> delegates = fvuDelegateTo.getFieldValue(issue);
if (delegates == null || delegates.size() == 0) return;
fvuDelegateToEmail.setFieldValue(issue, null);
removeUser(fvuToApprove, issue, currentUser)
for (ApplicationUser delegate:delegates) {
delegateNames += sep + delegate.getDisplayName();
sep = ", ";
addUser(fvuToApprove, issue, delegate)
addUser(fvuDelegateToEmail, issue, delegate)
}
fvuDelegateTo.setFieldValue(issue, null);
addComment(issue,currentUser, "Delegated to " + delegateNames, comment)
FieldValueUtil.persistIssueModifications(issue, currentUser.getName());
}
/**
* The list of approvers is being reset to a new list
*
* For all the new users (which are not listed in 'to approve', 'has rejected', 'has approved')
* Add the user to 'Approvers', 'to approve'
*
* For all the users which are not listed anymore (ie. the diff between the new approvers and the union
* of 'to approve', 'has rejected', 'has approved')
* Remove the user from the 'Approvers', 'to approve', 'has rejected', 'has approved'
*
* @param issue
*/
public static void changeApprovers(MutableIssue issue, String comment) {
ApplicationUser currentUser = jac.getUser();
List<ApplicationUser> newApprovers = fvuApprovers.getFieldValue(issue);
List<ApplicationUser> currentApprovers = collectApprovers(issue);
log.debug("Changing approvers");
for (ApplicationUser approver:newApprovers) {
if (! inList(currentApprovers, approver)) {
// this is a new approver
addUser(fvuToApprove, issue, approver);
}
}
for (ApplicationUser approver:currentApprovers) {
if (! inList(newApprovers, approver)) {
// this approver should be removed from the list
removeUser(fvuToApprove, issue, approver);
removeUser(fvuHasAccepted, issue, approver);
removeUser(fvuHasDeclined, issue, approver);
removeUser(fvuDelegateToEmail, issue, approver);
}
}
addComment(issue, currentUser, "changed approvers ", comment)
FieldValueUtil.persistIssueModifications(issue, currentUser.getName());
}
// The bypass function is provided such that a document can be accepted even if not fully approved
public static void byPass(MutableIssue issue) {
ApplicationUser currentUser = jac.getUser();
addComment(issue, currentUser, "bypassed", null);
}
/**
* checks if the user is member of the list
* @param applicationUsers
* @param applicationUser
* @return
*
*/
private static boolean inList(List<ApplicationUser> applicationUsers, ApplicationUser searchUser) {
if (searchUser == null) return false;
for (ApplicationUser user:applicationUsers) {
if (user.getUsername().equals(searchUser.getUsername())) return true;
}
return false;
}
/**
* Collect all users that are involved in approving this document
* These are the people that have accepted, declined and/or still need to approve.
* @param issue
* @return
*/
private static List<ApplicationUser> collectApprovers(MutableIssue issue) {
List<ApplicationUser> userList = new ArrayList<ApplicationUser>();
userList = addUsers(userList, (List<ApplicationUser>) fvuToApprove.getFieldValue(issue));
userList = addUsers(userList, (List<ApplicationUser>) fvuHasAccepted.getFieldValue(issue));
userList = addUsers(userList, (List<ApplicationUser>) fvuHasDeclined.getFieldValue(issue));
return userList;
}
// creates a new user list by merging two other user lists
public static List<ApplicationUser> addUsers(List<ApplicationUser> applicationUsers, List<ApplicationUser> users) {
for (ApplicationUser user: users) {
if (!inList(applicationUsers, user)) {
applicationUsers.add(user);
}
}
return applicationUsers;
}
/**
* Add a comment to the Approval Comment custom field. This custom field tracks the specific approval
* history of the document
*
* If multiple review rounds are in place, the rounds are in reverse order, but the actions
* within a round are ordered first to last.
*
* @param issue
* @param user
* @param operation
* @param comment
*/
private static void addComment(Issue issue, ApplicationUser user, String operation, String comment) {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MMM/yyyy HH:mm");
// Calculate what needs to be added
String userName = user.getDisplayName();
String inlineComment = (comment != null && comment.length() > 0) ?
"with following comment\n {quote}" + comment + "{quote}" :
"";
String commentExtension = "* ${userName} ${operation} on ${sdf.format(new Date())} ${inlineComment}\n"
// Split current comment between last review round and the rest. The last review round actions are at the top.
String currentApprovalComment = fvuApprovalComment.getString(issue);
String lastReviewRound;
String otherReviewRounds;
if(currentApprovalComment.startsWith(REVIEW_PROCESS_MARKER)) {
lastReviewRound = "";
otherReviewRounds = currentApprovalComment;
} else if(currentApprovalComment.contains(REVIEW_PROCESS_MARKER)) {
int justAfterFirstRound = currentApprovalComment.indexOf(REVIEW_PROCESS_MARKER);
lastReviewRound = currentApprovalComment.substring(0, justAfterFirstRound);
otherReviewRounds = currentApprovalComment.substring(justAfterFirstRound);
} else {
lastReviewRound = currentApprovalComment;
otherReviewRounds = "";
}
// Add the new comment at the end of the last round
lastReviewRound += commentExtension;
// Combine the last round with the rest again.
String newApprovalComment = lastReviewRound + otherReviewRounds;
fvuApprovalComment.setFieldValue(issue, newApprovalComment);
}
/**
* Log the start of a document review process.
*
* Add a comment who sent out the review request.
* If this is not the first round, also add a separation marker to the log.
*
* @param issue
*/
public static logStartOfReviewProcess(MutableIssue issue) {
// RECORD-57 Don't clear the Approval comment, but add a marker to it.
FieldValueUtil fvuApprovalComment = new FieldValueUtil("Approval comment")
def oldValue = fvuApprovalComment.getFieldValue(issue);
if (oldValue != null || oldValue != "") {
fvuApprovalComment.doSetFieldValue(issue, REVIEW_PROCESS_MARKER + oldValue)
}
// Log who sent out the review request
addComment(issue, jac.getUser(), 'sent documents for review', null)
}
// For testing purposes.
public static clearReviewComment(MutableIssue issue) {
fvuApprovalComment.clearFieldValue(issue)
}
// Remove a single user from the list
private static void removeUser(FieldValueUtil fieldValueUtil, Issue issue, ApplicationUser targetUser) {
List<ApplicationUser> userList = fieldValueUtil.getFieldValue(issue);
if (userList == null) return;
List<ApplicationUser> newList = new ArrayList<>();
for (ApplicationUser user:userList) {
if (user.getName() != targetUser.getName()) {
newList.add(user);
}
}
fieldValueUtil.doSetFieldValue(issue, newList);
}
// add a user from the list
private static void addUser(FieldValueUtil fieldValueUtil, Issue issue, ApplicationUser targetUser) {
List<ApplicationUser> userList = fieldValueUtil.getFieldValue(issue);
if (userList == null) userList = new ArrayList<>();
for (ApplicationUser user:userList) {
if (user.getName() == targetUser.getName()) {
return;
}
}
// the user is not member of the list
log.debug("Adding user ${targetUser.getName()} to the field ${fieldValueUtil.customField.getName()}");
userList.add(targetUser);
fieldValueUtil.doSetFieldValue(issue, userList);
}
}
|
Comments (1)
You can clone a snippet to your computer for local editing. Learn more.
Hi
I am wondering where can I get a copy of the class as referred to here?