View Javadoc

1   package plugin;
2   
3   import com.atlassian.jira.ComponentManager;
4   import com.atlassian.jira.issue.CustomFieldManager;
5   import com.atlassian.jira.issue.Issue;
6   import com.atlassian.jira.issue.IssueManager;
7   import com.atlassian.jira.issue.ModifiedValue;
8   import com.atlassian.jira.issue.fields.CustomField;
9   import com.atlassian.jira.issue.fields.CustomFieldImpl;
10  import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem;
11  import com.atlassian.jira.issue.fields.layout.field.FieldLayoutManager;
12  import com.atlassian.jira.issue.fields.layout.field.FieldLayoutStorageException;
13  import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
14  import com.atlassian.jira.project.Project;
15  import com.atlassian.jira.project.ProjectManager;
16  import org.apache.log4j.Logger;
17  import org.ofbiz.core.entity.GenericEntityException;
18  
19  import java.util.*;
20  
21  /**
22   * This class handles all the operations necessary to change the issues' value that are affected by an action made from
23   * the issue navigator, and also the methods that are used within the columnView_template file to help display in the issue navigator.
24   */
25  public class ValueAssigner {
26  
27      /**
28       * The default value that is assigned to the issue when no issue has an assigned value.
29       */
30      private static final double MAX_ORDER_VALUE = 100000;
31  
32      /**
33       * atlassian issue manager
34       */
35      IssueManager issueManager = null;
36  
37      /**
38       * Logger
39       */
40      private static final Logger logger = Logger.getLogger(FAIssueOrdererServlet.class);
41  
42  
43      public ValueAssigner() {
44      }
45  
46  
47      /**
48       * Set the given value to the given issue for the given custom field (which is of type NumberCFType)
49       *
50       * @param issue       The issue which the value will be assigned
51       * @param customField The concerned custom field
52       * @param orderValue       The order value that will be assigned to the issue
53       * @throws FieldLayoutStorageException Thrown if there is a problem trying to recover the FieldLayoutItem object
54       */
55      public void setValueToIssue(Issue issue, CustomField customField, double orderValue) throws FieldLayoutStorageException {
56          DefaultIssueChangeHolder issueChangeHolder = new DefaultIssueChangeHolder();
57          FieldLayoutManager layoutManager = ComponentManager.getInstance().getFieldLayoutManager();
58          FieldLayoutItem layoutItem = layoutManager.getFieldLayout(issue).getFieldLayoutItem(customField);
59  
60          ModifiedValue valeurParDefaut = new ModifiedValue(customField.getValue(issue), new Double(orderValue));
61          customField.updateValue(layoutItem, issue, valeurParDefaut, issueChangeHolder);
62      }
63  
64      /**
65       *
66       * @param issue The issue we want to check the value
67       * @param customField The corresponding custom field for the value
68       * @return true if the issue's value is greater than zero (used in the columnView_template file)
69       */
70      public boolean hasAValueGreaterThanZero(Issue issue, CustomField customField) {
71          Double valeur = (Double) customField.getValue(issue);
72          return (valeur.doubleValue()>0);
73      }
74  
75  
76      /**
77       * Method called from FAIssueOrdererServlet. Handle the different changes to do over the issues regarding the parameter obtained in the request
78       *
79       * @param customFieldName The name of the corresponding custom field
80       * @param action The action to execute
81       * @param issueKey The issue key
82       * @param issueOrderValue The issue value
83       * @param numberOfBoxes The number of boxes to move the issue
84       */
85      public void doChangeValue(String customFieldName, String action, String issueKey, String issueOrderValue, String numberOfBoxes) {
86          //We get the issue to modify
87          IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
88          Issue myIssue = issueManager.getIssueObject(issueKey);
89  
90          //We get the corresponding custom field
91          CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
92          CustomFieldImpl customField = (CustomFieldImpl) customFieldManager.getCustomFieldObjectByName(customFieldName);
93  
94          //We get the project's key by parsing the issue's key...
95          int cutoffIndex = issueKey.indexOf("-");
96          String projectKey = issueKey.substring(0, cutoffIndex);
97  
98          //We get the project the issue belongs to, so as to get all the issues' ids belonging to the project
99          ProjectManager projectManager = ComponentManager.getInstance().getProjectManager();
100         Project myProject = projectManager.getProjectObjByKey(projectKey);
101 
102         Collection issueIds = null;
103 
104         try {
105             issueIds = issueManager.getIssueIdsForProject(myProject.getId());
106         }
107         catch (GenericEntityException e) {
108             e.printStackTrace();
109         }
110 
111         //If the list of ids is not empty
112         if (issueIds != null) {
113             try {
114                 if (action.equals("up")) {
115                     increaseIssue(customField, myIssue, issueOrderValue, issueIds);
116                 } else if (action.equals("down")) {
117                     decreaseIssue(customField, myIssue, issueOrderValue, issueIds);
118                 } else if (action.equals("insert")) {
119                     assignValueAutomatically(customField, myIssue, issueIds);
120                 } else if (action.equals("first")) {
121                     moveIssueInFirstPosition(customField, myIssue, issueOrderValue, issueIds);
122                 } else if (action.equals("last")) {
123                     moveIssueInLastPosition(customField, myIssue, issueOrderValue, issueIds);
124                 } else if (action.equals("toBox")) {
125                     moveIssueToPosition(customField, myIssue, issueOrderValue, issueIds, numberOfBoxes);
126                 }
127             } catch (FieldLayoutStorageException e) {
128                 e.printStackTrace();
129             }
130         }
131     }
132 
133 
134     /**
135      * Exchange the values between myIssue and the issue which have a value just above issueValue
136      *
137      * @param customField The corresponding custom field
138      * @param myIssue The issue to modify
139      * @param issueOrderValue The issue value
140      * @param issueIds A list of ids of all the issue belonging to the same project than myIssue
141      * @throws FieldLayoutStorageException Thrown if there is a problem trying to recover the FieldLayoutItem object
142      */
143     public void increaseIssue(CustomFieldImpl customField, Issue myIssue, String issueOrderValue, Collection issueIds) throws FieldLayoutStorageException {
144         float value = Float.parseFloat(issueOrderValue);
145 
146         ArrayList issueAboveList = this.buildIssueAboveList(issueIds, customField, value);
147         Issue issueAbove = findIssueAbove(issueAboveList, customField, value);
148         if (issueAbove != null)
149             exchangeValues(myIssue, issueAbove, customField);
150     }
151 
152 
153     /**
154      * Exchange the values between myIssue and the issue which have a value just below issueValue. If there is no issue
155      * that have a value lower, myIssue is set to 0 value.
156      *
157      * @param customField The corresponding custom field
158      * @param myIssue The issue to modify
159      * @param issueOrderValue The issue value
160      * @param idsIssue A list of ids of all the issue belonging to the same project than myIssue
161      * @throws FieldLayoutStorageException Thrown if there is a problem trying to recover the FieldLayoutItem object
162      */
163     public void decreaseIssue(CustomFieldImpl customField, Issue myIssue, String issueOrderValue, Collection idsIssue) throws FieldLayoutStorageException {
164         //The issue that will be modify
165         Issue issueBelow;
166 
167         float value = Float.parseFloat(issueOrderValue);
168 
169         ArrayList issuesBelowList = this.buildIssueBelowList(idsIssue, customField, value);
170         issueBelow = findIssueBelow(issuesBelowList, customField, value);
171         if (issueBelow != null)
172             exchangeValues(myIssue, issueBelow, customField);
173 
174             //If there is no issue below, we set the value 0 to myIssue
175         else
176             setValueToIssue(myIssue, customField, 0);
177     }
178 
179 
180     /**
181      * Assign a value automatically to myIssue: if no issue has an order assigned value, the value is set to MAX_ORDER_VALUE.
182      * Else, the assigned value is the lower value found among all the issues that have an assigned value, divided by two.
183      *
184      * @param customField The corresponding custom field
185      * @param myIssue The issue that the value will be assign to.
186      * @param idsIssue A list of ids of all the issue belonging to the same project than myIssue
187      * @throws FieldLayoutStorageException Thrown if there is a problem trying to recover the FieldLayoutItem object
188      */
189     public void assignValueAutomatically(CustomFieldImpl customField, Issue myIssue, Collection idsIssue) throws FieldLayoutStorageException {
190         //Issue that will be modify
191         Issue issueAbove;
192 
193         ArrayList issueAboveList = this.buildIssueAboveList(idsIssue, customField, 0);
194         if (issueAboveList.size() != 0) {
195             issueAbove = findIssueAbove(issueAboveList, customField, 0);
196             insertIssue(myIssue, issueAbove, customField);
197         } else {
198             setValueToIssue(myIssue, customField, MAX_ORDER_VALUE);
199         }
200     }
201 
202 
203     /**
204      * Move an issue in first position, i.e. set the higher value found among all the issues that have an assigned value
205      * to myIssue. The order relation is preserved between the issues that had a greater value than issueValue.
206      *
207      * @param customField The corresponding custom field
208      * @param myIssue The issue to move in first position
209      * @param issueValue The value of myIssue
210      * @param issueIds A list of ids of all the issue belonging to the same project than myIssue
211      */
212     public void moveIssueInFirstPosition(CustomFieldImpl customField, Issue myIssue, String issueValue, Collection issueIds) {
213         ArrayList issueAboveList;
214         float value = Float.parseFloat(issueValue);
215 
216         issueAboveList = buildIssueAboveList(issueIds, customField, value);
217         if (issueAboveList.size() != 0) {
218             //Ascending sort
219             sortIssueList(issueAboveList, customField);
220 
221             for (int i = 0; i < issueAboveList.size(); i++) {
222                 Issue issueTmp = (Issue)issueAboveList.get(i);
223                 try {
224                     exchangeValues(myIssue, issueTmp, customField);
225                 }
226                 catch (FieldLayoutStorageException e) {
227                     e.printStackTrace();
228                 }
229             }
230         }
231     }
232 
233 
234     /**
235      * Move an issue in last position, i.e. set the lower value found among all the issues that have an assigned value
236      * to myIssue. The order relation is preserved between the issues that had a lower value than issueValue.
237      *
238      * @param customField The corresponding custom field
239      * @param myIssue The issue to move in last position
240      * @param issueValue The value of myIssue
241      * @param issueIds A list of ids of all the issue belonging to the same project than myIssue
242      */
243     public void moveIssueInLastPosition(CustomFieldImpl customField, Issue myIssue, String issueValue, Collection issueIds) {
244         ArrayList issueBelowList;
245         float value = Float.parseFloat(issueValue);
246 
247         issueBelowList = buildIssueBelowList(issueIds, customField, value);
248         if (issueBelowList.size() != 0) {
249             //Ascending sort
250             sortIssueList(issueBelowList, customField);
251 
252             for (int i = issueBelowList.size() - 1; i >= 0; i--) {
253                 Issue issueTmp = (Issue)issueBelowList.get(i);
254                 try {
255                     exchangeValues(myIssue, issueTmp, customField);
256                 }
257                 catch (FieldLayoutStorageException e){
258                     e.printStackTrace();
259                 }
260             }
261         }
262     }
263 
264 
265     /**
266      * Move an issue up or down, depending on the sign of s_nbOfBoxes, of s_nbOfBoxes boxes.
267      *
268      * @param customField The corresponding custom field
269      * @param myIssue The issue to move
270      * @param issueValue The value of myIssue
271      * @param issueIds A list of ids of all the issue belonging to the same project than myIssue
272      * @param s_nbOfBoxes The number of boxes that myIssue will move.
273      */
274     public void moveIssueToPosition(CustomFieldImpl customField, Issue myIssue, String issueValue, Collection issueIds, String s_nbOfBoxes) {
275         ArrayList issueList;
276         float value = Float.parseFloat(issueValue);
277 
278         int numberOfBoxes = 0;
279         try {
280             numberOfBoxes = Integer.parseInt(s_nbOfBoxes);
281         } catch (NumberFormatException e) {
282             // stay with zero
283         }
284 
285         //Increase the issue
286         if (numberOfBoxes > 0) {
287             issueList = buildIssueAboveList(issueIds, customField, value);
288             if (issueList.size() != 0) {
289                 //Ascending sort
290                 sortIssueList(issueList, customField);
291 
292                 for (int i = 0; i < issueList.size(); i++) {
293                     if (numberOfBoxes > 0) {
294                         Issue issueTmp = (Issue)issueList.get(i);
295                         try {
296                             exchangeValues(myIssue, issueTmp, customField);
297                         }
298                         catch (FieldLayoutStorageException e){
299                             e.printStackTrace();
300                         }
301                         numberOfBoxes--;
302                     }
303                 }
304             }
305         }
306 
307         //Decrease the issue
308         else if (numberOfBoxes < 0) {
309             issueList = buildIssueBelowList(issueIds, customField, value);
310             if (issueList.size() != 0) {
311                 //Ascending sort
312                 sortIssueList(issueList, customField);
313 
314                 for (int i = issueList.size() - 1; i >= 0; i--) {
315                     if (numberOfBoxes < 0) {
316                         Issue issueTmp = (Issue)issueList.get(i);
317                         try {
318                             exchangeValues(myIssue, issueTmp, customField);
319                         }
320                         catch (FieldLayoutStorageException e){
321                             e.printStackTrace();
322                         }
323                         numberOfBoxes++;
324                     }
325                 }
326             }
327         }
328     }
329 
330 
331     /**
332      * Return the issue that have the lower value greater than issueValue
333      *
334      * @param issueList A list of all the issues that have a greater value than issueValue (to get this list, use )
335      * @param customField The corresponding custom field
336      * @param issueValue The value of the issue to modify
337      * @return issueTmp The issue that have the lower value among all the issues that have a greater value than issueValue
338      */
339     public Issue findIssueAbove(ArrayList issueList, CustomFieldImpl customField, float issueValue) {
340         Issue issueTmp = null;
341         float valueTmp = 0;
342         boolean isInitialized = false;
343 
344         for (int i = 0; i < issueList.size(); i++) {
345 
346             Issue actualIssue = (Issue) issueList.get(i);
347             Object actualValue = customField.getValue(actualIssue);
348 
349             //If the issue has a value assigned.
350             if (actualValue != null) {
351                 float value = Float.parseFloat(actualValue.toString());
352 
353                 if (value > issueValue) {
354                     //When we first pass in the loop
355                     if (!isInitialized) {
356                         valueTmp = value;
357                         issueTmp = actualIssue;
358                         isInitialized = true;
359                     }
360 
361                     //For the other times that we pass in the loop
362                     else if (value < valueTmp) {
363                         //On redefinit la nouvelle valeur et l'issue
364                         valueTmp = value;
365                         issueTmp = actualIssue;
366                     }
367                 }
368             }
369         }
370         return issueTmp;
371     }
372 
373 
374     /**
375      * Return the issue that have the greater value lower than issueValue
376      *
377      * @param issueList A list of all the issues that have a lower value than issueValue (to get this list, use )
378      * @param customField The corresponding custom field
379      * @param issueValue The value of the issue to modify
380      * @return issueTmp The issue that have the greater value among all the issues that have a lower value than issueValue
381      */
382     public Issue findIssueBelow(ArrayList issueList, CustomFieldImpl customField, float issueValue) {
383         Issue issueTmp = null;
384         float valueTmp = 0;
385         boolean isInitialized = false;
386 
387         for (int i = 0; i < issueList.size(); i++) {
388 
389             Issue actualIssue = (Issue) issueList.get(i);
390             Object valeurActuelle = customField.getValue(actualIssue);
391 
392             if (valeurActuelle != null) {
393                 float poidsIssue = Float.parseFloat(valeurActuelle.toString());
394 
395                 if (poidsIssue < issueValue) {
396                     //When we first pass in the loop
397                     if (!isInitialized) {
398                         valueTmp = poidsIssue;
399                         issueTmp = actualIssue;
400                         isInitialized = true;
401                     }
402 
403                     //For the other times that we pass in the loop
404                     else if (poidsIssue > valueTmp) {
405                         valueTmp = poidsIssue;
406                         issueTmp = actualIssue;
407                     }
408                 }
409             }
410         }
411         return issueTmp;
412     }
413 
414 
415     /**
416      * Exchange the values between issue1 and issue2, according to the given custom field
417      *
418      * @param issue1 The first issue to modify
419      * @param issue2 The second issue to modify
420      * @param customField The corresponding custom field
421      * @throws FieldLayoutStorageException Thrown if there is a problem trying to recover the FieldLayoutItem object
422      */
423     public void exchangeValues(Issue issue1, Issue issue2, CustomFieldImpl customField) throws FieldLayoutStorageException {
424         DefaultIssueChangeHolder issueChangeHolder = new DefaultIssueChangeHolder();
425         FieldLayoutManager layoutManager = ComponentManager.getInstance().getFieldLayoutManager();
426         FieldLayoutItem layoutItem = layoutManager.getFieldLayout(issue1).getFieldLayoutItem(customField);
427 
428         ModifiedValue issue1NewValue = new ModifiedValue(customField.getValue(issue1), customField.getValue(issue2));
429         ModifiedValue issue2NewValue = new ModifiedValue(customField.getValue(issue2), customField.getValue(issue1));
430         customField.updateValue(layoutItem, issue1, issue1NewValue, issueChangeHolder);
431         customField.updateValue(layoutItem, issue2, issue2NewValue, issueChangeHolder);
432     }
433 
434 
435     /**
436      * Insert an issue, i.e. set to it a calculated value, so as to could order it in the issue navigator.
437      *
438      * @param myIssue The issue that the value will be assigned to
439      * @param issueAbove The issue that have the lower value among all the issues that have an assigned value
440      * @param customField The corresponding custom field
441      * @throws FieldLayoutStorageException Thrown if there is a problem trying to recover the FieldLayoutItem object
442      */
443     public void insertIssue(Issue myIssue, Issue issueAbove, CustomFieldImpl customField) throws FieldLayoutStorageException {
444         DefaultIssueChangeHolder issueChangeHolder = new DefaultIssueChangeHolder();
445         FieldLayoutManager layoutManager = ComponentManager.getInstance().getFieldLayoutManager();
446         FieldLayoutItem layoutItem = layoutManager.getFieldLayout(myIssue).getFieldLayoutItem(customField);
447 
448         float valueFound = Float.parseFloat(customField.getValue(issueAbove).toString());
449         Double newValue = new Double(valueFound / 2);
450 
451         ModifiedValue modifiedValue = new ModifiedValue(null, newValue);
452         customField.updateValue(layoutItem, myIssue, modifiedValue, issueChangeHolder);
453     }
454 
455 
456     /**
457      * Return a list of issues which have a value greater than minValue
458      *
459      * @param issueIds A list of ids of all the issue belonging to the same project than myIssue
460      * @param customField The corresponding custom field
461      * @param minValue The minimum value that an issue must have to be selected
462      * @return issueAboveList A list of all the issues that have a an assigned value greater than minValue
463      */
464     public ArrayList buildIssueAboveList(Collection issueIds, CustomFieldImpl customField, double minValue) {
465         int listSize = issueIds.size();
466         ArrayList issueAboveList = new ArrayList(listSize);
467 
468         IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
469         Iterator iterator = issueIds.iterator();
470 
471         while (iterator.hasNext()) {
472             Long issueId = (Long) iterator.next();
473             Issue issue = issueManager.getIssueObject(issueId);
474             try {
475                 if (((Double) customField.getValue(issue)).doubleValue() > minValue) {
476                     issueAboveList.add(issue);
477                 }
478             } catch (NullPointerException e){
479                 e.printStackTrace();
480             }
481         }
482         issueAboveList.trimToSize();
483         return issueAboveList;
484     }
485 
486 
487     /**
488      * Return a list of issues which have a value lower than maxValue
489      *
490      * @param issueIds A list of ids of all the issue belonging to the same project than myIssue
491      * @param customField The corresponding custom field
492      * @param maxValue The maximum value that an issue must have to be selected
493      * @return issueAboveList A list of all the issues that have a an assigned value lower than minValue
494      */
495     public ArrayList buildIssueBelowList(Collection issueIds, CustomFieldImpl customField, double maxValue) {
496         int listSize = issueIds.size();
497         ArrayList issueBelowList = new ArrayList(listSize);
498 
499         IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
500         Iterator iterator = issueIds.iterator();
501 
502         while (iterator.hasNext()) {
503             Long issueId = (Long) iterator.next();
504             Issue issueTmp = issueManager.getIssueObject(issueId);
505             try {
506                 if (((Double) customField.getValue(issueTmp)).doubleValue() < maxValue && ((Double) customField.getValue(issueTmp)).doubleValue() > 0)
507                     issueBelowList.add(issueTmp);
508             } catch (NullPointerException e) {
509                 e.printStackTrace();
510             }
511         }
512         issueBelowList.trimToSize();
513         return issueBelowList;
514     }
515 
516 
517     /**
518      * Sort a list of issues in ascending order, according to their assigned value.
519      *
520      * @param issueList The list of issues to be sorted
521      * @param customField The corresponding custom field
522      */
523     public void sortIssueList(ArrayList issueList, CustomFieldImpl customField) {
524 
525         // design could be improved using a TreeMap
526         HashMap issues = new HashMap();
527         ArrayList issuesValues = new ArrayList(issueList.size());
528 
529         for (int i = 0; i < issueList.size(); i++) {
530             Issue issueTmp = (Issue)issueList.get(i);
531             issues.put((Double)customField.getValue(issueTmp), issueTmp);
532             issuesValues.add((Double)customField.getValue(issueTmp));
533         }
534 
535         Collections.sort(issuesValues);
536         for (int i = 0; i < issuesValues.size(); i++) {
537             issueList.set(i, issues.get(issuesValues.get(i)));
538         }
539     }
540 
541 
542     /**
543      * Return true if issue has the higher value among all the issue belonging to the same project (used from the
544      * columView_template file to manage the display of the tools)
545      *
546      * @param issue The issue to check
547      * @param customField The corresponding custom field
548      * @return true if issue has the higher assigned value 
549      */
550     public boolean isFirst(Issue issue, CustomField customField) {
551         boolean isFirst = false;
552         IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
553 
554         //We get the project's key by parsing the issue's key...
555         int cutoffIndex = issue.getKey().indexOf("-");
556         String projectKey = issue.getKey().substring(0, cutoffIndex);
557 
558         //We get the project the issue belongs to, so as to get all the issues' ids belonging to the project
559         ProjectManager projectManager = ComponentManager.getInstance().getProjectManager();
560         Project project = projectManager.getProjectObjByKey(projectKey);
561 
562         Collection issueIds = null;
563 
564         try {
565             issueIds = issueManager.getIssueIdsForProject(project.getId());
566         }
567         catch (GenericEntityException e) {
568             e.printStackTrace();
569         }
570 
571         ArrayList issuesAbove = buildIssueAboveList(issueIds, (CustomFieldImpl) customField, ((Double) customField.getValue(issue)).doubleValue());
572         if (issuesAbove.size() == 0)
573             isFirst = true;
574 
575         return isFirst;
576     }
577 
578 
579     /**
580      * Return true if issue has the lower value among all the issue belonging to the same project (used from the
581      * columView_template file to manage the display of the tools)
582      *
583      * @param issue The issue to check
584      * @param customField The corresponding custom field
585      * @return true if issue has the lower assigned value
586      */
587     public boolean isLast(Issue issue, CustomField customField) {
588         boolean isLast = false;
589         IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
590 
591         //We get the project's key by parsing the issue's key...
592         int cutoffIndex = issue.getKey().indexOf("-");
593         String projectKey = issue.getKey().substring(0, cutoffIndex);
594 
595         //We get the project the issue belongs to, so as to get all the issues' ids belonging to the project
596         ProjectManager projectManager = ComponentManager.getInstance().getProjectManager();
597         Project project = projectManager.getProjectObjByKey(projectKey);
598 
599         Collection issueIds = null;
600 
601         try {
602             issueIds = issueManager.getIssueIdsForProject(project.getId());
603         }
604         catch (GenericEntityException e) {
605             e.printStackTrace();
606         }
607 
608         ArrayList issuesBelow = buildIssueBelowList(issueIds, (CustomFieldImpl) customField, ((Double) customField.getValue(issue)).doubleValue());
609         if (issuesBelow.size() == 0)
610             isLast = true;
611 
612         return isLast;
613     }
614 
615 
616     /**
617      * Display the key and the value for each issue in the list
618      *
619      * @param issues A list of issues
620      * @param customField The corresponding custom field for the value to display
621      */
622     public void displayIssuesValue(ArrayList issues, CustomFieldImpl customField) {
623         logger.warn("Values: \n");
624         for (int i = 0; i < issues.size(); i++) {
625             Issue issue = (Issue) issues.get(i);
626             try {
627                 logger.warn(issue.getKey() + " - " + customField.getValue(issue).toString());
628             } catch (NullPointerException e) {
629                 e.printStackTrace();
630             }
631         }
632     }
633 
634 }
635