@@ -44,7 +44,7 @@ public class SubtaskTemplateImportAction extends JiraWebActionSupport {
4444
4545 private static final String QUICK_SUBTASKS_PROJECT_TEMPLATES = "com.hascode.plugin.jira:subtask-templates" ;
4646 private static final String QUICK_SUBTASKS_USER_TEMPLATES_PREFIX = "subtasks-user-" ;
47- private static final Pattern QUICK_SUBTASKS_TASK_PATTERN = Pattern .compile ("^\\ s*- *([^/]+)/?(?:\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]+ )\" )?\\ s*/?\\ s*|[^\\ r\\ n]*)$" );
47+ private static final Pattern QUICK_SUBTASKS_TASK_PATTERN = Pattern .compile ("^\\ s*- *([^/]+)/?(?:\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*(?: ([^:]+):\" ([^\" ]* )\" )?\\ s*/?\\ s*|[^\\ r\\ n]*)$" );
4848 private static final String NEWLINE = "\n " ;
4949
5050 private final UserSearchService userSearchService ;
@@ -285,66 +285,68 @@ String transformQuickSubtasksTemplate(String templateString) {
285285 key = matcher .group (i );
286286 } else {
287287 value = matcher .group (i );
288- switch (key .toLowerCase ()) {
289- // same keyword and value format
290- case "priority" :
291- case "description" :
292- case "estimate" :
293- case "assignee" :
294- case "reporter" :
295- output .append (" " ).append (key .toLowerCase ()).append (": " ).append (value ).append (NEWLINE );
296- break ;
297- // different keyword same value
298- case "issuetype" :
299- output .append (" " ).append (Subtask .Attributes .ISSUE_TYPE ).append (": " ).append (value ).append (NEWLINE );
300- break ;
301- case "duedate" :
302- output .append (" " ).append (Subtask .Attributes .DUE_DATE ).append (": " ).append (value ).append (NEWLINE );
303- break ;
304- case "fixversion" :
305- output .append (" " ).append (Subtask .Attributes .FIX_VERSION ).append (": " ).append (value ).append (NEWLINE );
306- break ;
307- case "affectedversion" :
308- output .append (" " ).append (Subtask .Attributes .AFFECTED_VERSION ).append (": " ).append (value ).append (NEWLINE );
309- break ;
310- // component (split values)
311- case "component" :
312- String [] components = value .split (", *" );
313- Arrays .stream (components ).forEach (component ->
314- output .append (" " ).append (Subtask .Attributes .COMPONENT ).append (": " ).append (component ).append (NEWLINE )
315- );
316- break ;
317- // labels (split values)
318- case "labels" :
319- String [] labels = value .split (", *" );
320- Arrays .stream (labels ).forEach (label ->
321- output .append (" " ).append (Subtask .Attributes .LABEL ).append (": " ).append (label ).append (NEWLINE )
322- );
323- break ;
324- // watcher (split values)
325- case "watcher" :
326- String [] watchers = value .split (", *" );
327- Arrays .stream (watchers ).forEach (watcher ->
328- output .append (" " ).append (Subtask .Attributes .WATCHER ).append (": " ).append (watcher ).append (NEWLINE )
329- );
330- break ;
331- // custom fields
332- case "cfield" :
333- String [] tokens = value .split (":" , 2 );
334- if (tokens .length == 2 ) {
335- String customFieldName = tokens [0 ]
336- .replaceAll ("\\ (" , "\\ \\ (" )
337- .replaceAll ("\\ )" , "\\ \\ )" )
338- .replaceAll (":" , "\\ :" )
339- .trim ();
340- output .append (" " ).append ("customfield(" ).append (customFieldName ).append ("): " ).append (tokens [1 ]).append (NEWLINE );
341- } else {
342- log .error ("Invalid custom field attributes: " + value );
343- }
344- break ;
345- // not supported (will be ignored)
346- default :
347- log .error ("Ignoring unknown attribute '" + key + "' with value: '" + value + "'" );
288+ if (value != null && !value .isEmpty ()) {
289+ switch (key .toLowerCase ()) {
290+ // same keyword and value format
291+ case "priority" :
292+ case "description" :
293+ case "estimate" :
294+ case "assignee" :
295+ case "reporter" :
296+ output .append (" " ).append (key .toLowerCase ()).append (": " ).append (value ).append (NEWLINE );
297+ break ;
298+ // different keyword same value
299+ case "issuetype" :
300+ output .append (" " ).append (Subtask .Attributes .ISSUE_TYPE ).append (": " ).append (value ).append (NEWLINE );
301+ break ;
302+ case "duedate" :
303+ output .append (" " ).append (Subtask .Attributes .DUE_DATE ).append (": " ).append (value ).append (NEWLINE );
304+ break ;
305+ case "fixversion" :
306+ output .append (" " ).append (Subtask .Attributes .FIX_VERSION ).append (": " ).append (value ).append (NEWLINE );
307+ break ;
308+ case "affectedversion" :
309+ output .append (" " ).append (Subtask .Attributes .AFFECTED_VERSION ).append (": " ).append (value ).append (NEWLINE );
310+ break ;
311+ // component (split values)
312+ case "component" :
313+ String [] components = value .split (", *" );
314+ Arrays .stream (components ).forEach (component ->
315+ output .append (" " ).append (Subtask .Attributes .COMPONENT ).append (": " ).append (component ).append (NEWLINE )
316+ );
317+ break ;
318+ // labels (split values)
319+ case "labels" :
320+ String [] labels = value .split (", *" );
321+ Arrays .stream (labels ).forEach (label ->
322+ output .append (" " ).append (Subtask .Attributes .LABEL ).append (": " ).append (label ).append (NEWLINE )
323+ );
324+ break ;
325+ // watcher (split values)
326+ case "watcher" :
327+ String [] watchers = value .split (", *" );
328+ Arrays .stream (watchers ).forEach (watcher ->
329+ output .append (" " ).append (Subtask .Attributes .WATCHER ).append (": " ).append (watcher ).append (NEWLINE )
330+ );
331+ break ;
332+ // custom fields
333+ case "cfield" :
334+ String [] tokens = value .split (":" , 2 );
335+ if (tokens .length == 2 ) {
336+ String customFieldName = tokens [0 ]
337+ .replaceAll ("\\ (" , "\\ \\ (" )
338+ .replaceAll ("\\ )" , "\\ \\ )" )
339+ .replaceAll (":" , "\\ :" )
340+ .trim ();
341+ output .append (" " ).append ("customfield(" ).append (customFieldName ).append ("): " ).append (tokens [1 ]).append (NEWLINE );
342+ } else {
343+ log .error ("Invalid custom field attributes: " + value );
344+ }
345+ break ;
346+ // not supported (will be ignored)
347+ default :
348+ log .error ("Ignoring unknown attribute '" + key + "' with value: '" + value + "'" );
349+ }
348350 }
349351 }
350352 } else {
0 commit comments