1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.itracker.services.util;
20
21 import java.text.SimpleDateFormat;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29 import java.util.MissingResourceException;
30 import java.util.Set;
31
32 import org.apache.log4j.Logger;
33 import org.itracker.core.resources.ITrackerResources;
34 import org.itracker.model.Configuration;
35 import org.itracker.model.CustomField;
36 import org.itracker.model.Issue;
37 import org.itracker.model.IssueActivityType;
38 import org.itracker.model.IssueRelation;
39 import org.itracker.model.NameValuePair;
40 import org.itracker.model.Notification;
41 import org.itracker.model.PermissionType;
42 import org.itracker.model.Project;
43 import org.itracker.model.User;
44 import org.itracker.web.util.ServletContextUtils;
45
46
47
48
49 public class IssueUtilities {
50
51 private static final Logger log = Logger.getLogger(IssueUtilities.class);
52 public static final int FIELD_TYPE_SINGLE = 1;
53 public static final int FIELD_TYPE_INDEXED = 2;
54 public static final int FIELD_TYPE_MAP = 3;
55
56 public static final int FIELD_ID = -1;
57 public static final int FIELD_DESCRIPTION = -2;
58 public static final int FIELD_STATUS = -3;
59 public static final int FIELD_RESOLUTION = -4;
60 public static final int FIELD_SEVERITY = -5;
61 public static final int FIELD_CREATOR = -6;
62 public static final int FIELD_CREATEDATE = -7;
63 public static final int FIELD_OWNER = -8;
64 public static final int FIELD_LASTMODIFIED = -9;
65 public static final int FIELD_PROJECT = -10;
66 public static final int FIELD_TARGET_VERSION = -11;
67 public static final int FIELD_COMPONENTS = -12;
68 public static final int FIELD_VERSIONS = -13;
69 public static final int FIELD_ATTACHMENTDESCRIPTION = -14;
70 public static final int FIELD_ATTACHMENTFILENAME = -15;
71 public static final int FIELD_HISTORY = -16;
72
73 protected static final int[] STANDARD_FIELDS = { FIELD_ID,
74 FIELD_DESCRIPTION, FIELD_STATUS, FIELD_RESOLUTION, FIELD_SEVERITY,
75 FIELD_CREATOR, FIELD_CREATEDATE, FIELD_OWNER, FIELD_LASTMODIFIED,
76 FIELD_PROJECT, FIELD_TARGET_VERSION, FIELD_COMPONENTS,
77 FIELD_VERSIONS, FIELD_ATTACHMENTDESCRIPTION,
78 FIELD_ATTACHMENTFILENAME, FIELD_HISTORY };
79
80 public static final int STATUS_NEW = 100;
81 public static final int STATUS_UNASSIGNED = 200;
82 public static final int STATUS_ASSIGNED = 300;
83 public static final int STATUS_RESOLVED = 400;
84 public static final int STATUS_CLOSED = 500;
85
86
87
88
89 public static final int STATUS_END = 600;
90
91 public static final int HISTORY_STATUS_REMOVED = -1;
92 public static final int HISTORY_STATUS_AVAILABLE = 1;
93
94
95 public static final int RELATION_TYPE_RELATED_P = 1;
96
97 public static final int RELATION_TYPE_RELATED_C = 2;
98
99 public static final int RELATION_TYPE_DUPLICATE_P = 3;
100
101 public static final int RELATION_TYPE_DUPLICATE_C = 4;
102
103 public static final int RELATION_TYPE_CLONED_P = 5;
104
105 public static final int RELATION_TYPE_CLONED_C = 6;
106
107 public static final int RELATION_TYPE_SPLIT_P = 7;
108
109 public static final int RELATION_TYPE_SPLIT_C = 8;
110
111 public static final int RELATION_TYPE_DEPENDENT_P = 9;
112
113 public static final int RELATION_TYPE_DEPENDENT_C = 10;
114
115 public static final int NUM_RELATION_TYPES = 10;
116
117 private static List<Configuration> resolutions = new ArrayList<Configuration>();
118 private static List<Configuration> severities = new ArrayList<Configuration>();
119 private static List<Configuration> statuses = new ArrayList<Configuration>();
120 private static List<CustomField> customFields = new ArrayList<CustomField>();
121 private static final Logger logger = Logger.getLogger(IssueUtilities.class);
122
123 public IssueUtilities() {
124 }
125
126 public static int getFieldType(Integer fieldId) {
127 if (fieldId != null) {
128 if (fieldId.intValue() > 0) {
129 return FIELD_TYPE_MAP;
130 }
131
132
133
134
135
136 }
137
138 return FIELD_TYPE_SINGLE;
139 }
140
141 public static String getFieldName(Integer fieldId) {
142 if (fieldId == null) {
143 return "";
144 }
145
146 if (fieldId.intValue() > 0) {
147 return "customFields";
148 }
149
150 switch (fieldId.intValue()) {
151 case FIELD_ID:
152 return "id";
153 case FIELD_DESCRIPTION:
154 return "description";
155 case FIELD_STATUS:
156 return "status";
157 case FIELD_RESOLUTION:
158 return "resolution";
159 case FIELD_SEVERITY:
160 return "severity";
161 case FIELD_CREATOR:
162 return "creatorId";
163 case FIELD_CREATEDATE:
164 return "createdate";
165 case FIELD_OWNER:
166 return "ownerId";
167 case FIELD_LASTMODIFIED:
168 return "lastmodified";
169 case FIELD_PROJECT:
170 return "projectId";
171 case FIELD_TARGET_VERSION:
172 return "targetVersion";
173 case FIELD_COMPONENTS:
174 return "components";
175 case FIELD_VERSIONS:
176 return "versions";
177 case FIELD_ATTACHMENTDESCRIPTION:
178 return "attachmentDescription";
179 case FIELD_ATTACHMENTFILENAME:
180 return "attachment";
181 case FIELD_HISTORY:
182 return "history";
183 default:
184 return "";
185 }
186 }
187
188 public static String getFieldName(Integer fieldId,
189 List<CustomField> customFields, Locale locale) {
190 if (fieldId.intValue() < 0) {
191 return ITrackerResources.getString(getStandardFieldKey(fieldId
192 .intValue()), locale);
193 } else {
194 for (int i = 0; i < customFields.size(); i++) {
195 if (fieldId.equals(customFields.get(i).getId())) {
196 return CustomFieldUtilities.getCustomFieldName(fieldId,
197 locale);
198 }
199 }
200 }
201
202 return ITrackerResources.getString("itracker.web.generic.unknown",
203 locale);
204 }
205
206 public static String getStandardFieldKey(int fieldId) {
207 switch (fieldId) {
208 case FIELD_ID:
209 return "itracker.web.attr.id";
210 case FIELD_DESCRIPTION:
211 return "itracker.web.attr.description";
212 case FIELD_STATUS:
213 return "itracker.web.attr.status";
214 case FIELD_RESOLUTION:
215 return "itracker.web.attr.resolution";
216 case FIELD_SEVERITY:
217 return "itracker.web.attr.severity";
218 case FIELD_CREATOR:
219 return "itracker.web.attr.creator";
220 case FIELD_CREATEDATE:
221 return "itracker.web.attr.createdate";
222 case FIELD_OWNER:
223 return "itracker.web.attr.owner";
224 case FIELD_LASTMODIFIED:
225 return "itracker.web.attr.lastmodified";
226 case FIELD_PROJECT:
227 return "itracker.web.attr.project";
228 case FIELD_TARGET_VERSION:
229 return "itracker.web.attr.target";
230 case FIELD_COMPONENTS:
231 return "itracker.web.attr.components";
232 case FIELD_VERSIONS:
233 return "itracker.web.attr.versions";
234 case FIELD_ATTACHMENTDESCRIPTION:
235 return "itracker.web.attr.attachmentdescription";
236 case FIELD_ATTACHMENTFILENAME:
237 return "itracker.web.attr.attachmentfilename";
238 case FIELD_HISTORY:
239 return "itracker.web.attr.detaileddescription";
240 default:
241 return "itracker.web.generic.unknown";
242 }
243 }
244
245 public static NameValuePair[] getStandardFields(Locale locale) {
246 NameValuePair[] fieldNames = new NameValuePair[STANDARD_FIELDS.length];
247 for (int i = 0; i < STANDARD_FIELDS.length; i++) {
248 fieldNames[i] = new NameValuePair(ITrackerResources.getString(
249 getStandardFieldKey(STANDARD_FIELDS[i]), locale), Integer
250 .toString(STANDARD_FIELDS[i]));
251 }
252 return fieldNames;
253 }
254
255 public static String getRelationName(int value) {
256 return getRelationName(value, ITrackerResources.getLocale());
257 }
258
259 public static String getRelationName(int value, Locale locale) {
260 return getRelationName(Integer.toString(value), locale);
261 }
262
263 public static String getRelationName(String value, Locale locale) {
264 return ITrackerResources.getString(
265 ITrackerResources.KEY_BASE_ISSUE_RELATION + value, locale);
266 }
267
268 public static int getMatchingRelationType(int relationType) {
269 switch (relationType) {
270 case RELATION_TYPE_RELATED_P:
271 return RELATION_TYPE_RELATED_C;
272 case RELATION_TYPE_RELATED_C:
273 return RELATION_TYPE_RELATED_P;
274 case RELATION_TYPE_DUPLICATE_P:
275 return RELATION_TYPE_DUPLICATE_C;
276 case RELATION_TYPE_DUPLICATE_C:
277 return RELATION_TYPE_DUPLICATE_P;
278 case RELATION_TYPE_CLONED_P:
279 return RELATION_TYPE_CLONED_C;
280 case RELATION_TYPE_CLONED_C:
281 return RELATION_TYPE_CLONED_P;
282 case RELATION_TYPE_SPLIT_P:
283 return RELATION_TYPE_SPLIT_C;
284 case RELATION_TYPE_SPLIT_C:
285 return RELATION_TYPE_SPLIT_P;
286 case RELATION_TYPE_DEPENDENT_P:
287 return RELATION_TYPE_DEPENDENT_C;
288 case RELATION_TYPE_DEPENDENT_C:
289 return RELATION_TYPE_DEPENDENT_P;
290 default:
291 return -1;
292 }
293 }
294
295 public static String componentsToString(Issue issue) {
296 StringBuffer value = new StringBuffer();
297 if (issue != null && issue.getComponents().size() > 0) {
298 for (int i = 0; i < issue.getComponents().size(); i++) {
299 value.append((i != 0 ? ", " : "")
300 + issue.getComponents().get(i).getName());
301 }
302 }
303 return value.toString();
304 }
305
306 public static String versionsToString(Issue issue) {
307 StringBuffer value = new StringBuffer();
308 if (issue != null && issue.getVersions().size() > 0) {
309 for (int i = 0; i < issue.getVersions().size(); i++) {
310 value.append((i != 0 ? ", " : "")
311 + issue.getVersions().get(i).getNumber());
312 }
313 }
314 return value.toString();
315 }
316
317 public static String historyToString(Issue issue, SimpleDateFormat sdf) {
318 StringBuffer value = new StringBuffer();
319 if (issue != null && issue.getHistory().size() > 0 && sdf != null) {
320 for (int i = 0; i < issue.getHistory().size(); i++) {
321 value.append((i != 0 ? "," : "")
322 + issue.getHistory().get(i).getDescription() + ","
323 + issue.getHistory().get(i).getUser().getFirstName());
324 value.append(" "
325 + issue.getHistory().get(i).getUser().getLastName()
326 + ","
327 + sdf.format(issue.getHistory().get(i)
328 .getLastModifiedDate()));
329 }
330 }
331 return value.toString();
332 }
333
334 public static String getStatusName(Integer value) {
335 return getStatusName(value, ITrackerResources.getLocale());
336 }
337
338 public static String getStatusName(int value, Locale locale) {
339 return getStatusName(Integer.toString(value), locale);
340 }
341
342 public static String getStatusName(String value, Locale locale) {
343 return ITrackerResources.getString(ITrackerResources.KEY_BASE_STATUS
344 + value, locale);
345 }
346
347
348
349
350
351 public static List<Configuration> getStatuses() {
352 return statuses;
353 }
354
355 public static List<NameValuePair> getStatuses(Locale locale) {
356 NameValuePair[] statusStrings = new NameValuePair[statuses.size()];
357 for (int i = 0; i < statuses.size(); i++) {
358 statusStrings[i] = new NameValuePair(ITrackerResources.getString(
359 ITrackerResources.KEY_BASE_STATUS
360 + statuses.get(i).getValue(), locale), statuses
361 .get(i).getValue());
362 }
363 return Arrays.asList(statusStrings);
364 }
365
366 public static void setStatuses(List<Configuration> value) {
367 statuses = (value == null ? new ArrayList<Configuration>() : value);
368 }
369
370 public static int getNumberStatuses() {
371 return statuses.size();
372 }
373
374 public static String getSeverityName(Integer value) {
375 return getSeverityName(value, ITrackerResources.getLocale());
376 }
377
378 public static String getSeverityName(int value, Locale locale) {
379 return getSeverityName(Integer.toString(value), locale);
380 }
381
382 public static String getSeverityName(String value, Locale locale) {
383 return ITrackerResources.getString(ITrackerResources.KEY_BASE_SEVERITY
384 + value, locale);
385 }
386
387
388
389
390
391
392
393
394
395
396
397 public static List<NameValuePair> getSeverities(Locale locale) {
398 List<NameValuePair> severityStrings = new ArrayList<NameValuePair>();
399
400 for (int i = 0; i < severities.size(); i++) {
401 String string1 = ITrackerResources.getString(
402 ITrackerResources.KEY_BASE_SEVERITY
403 + severities.get(i).getValue(), locale);
404 String string2 = severities.get(i).getValue();
405 NameValuePair nvp = new NameValuePair(string1, string2);
406 severityStrings.add(i, nvp);
407 }
408 return severityStrings;
409 }
410
411 public static void setSeverities(List<Configuration> value) {
412 severities = (value == null ? new ArrayList<Configuration>() : value);
413 }
414
415 public static int getNumberSeverities() {
416 return severities.size();
417 }
418
419
420
421
422
423
424
425
426
427
428
429
430
431 public static int compareSeverity(Issue issueA, Issue issueB) {
432 if (issueA == null && issueB == null) {
433 return 0;
434 } else if (issueA == null && issueB != null) {
435 return -1;
436 } else if (issueA != null && issueB == null) {
437 return 1;
438 } else {
439 int issueAIndex = Integer.MAX_VALUE;
440 int issueBIndex = Integer.MAX_VALUE;
441 for (int i = 0; i < severities.size(); i++) {
442 if (severities.get(i) != null) {
443 if (severities.get(i).getValue().equalsIgnoreCase(
444 Integer.toString(issueA.getSeverity()))) {
445 issueAIndex = i;
446 }
447 if (severities.get(i).getValue().equalsIgnoreCase(
448 Integer.toString(issueB.getSeverity()))) {
449 issueBIndex = i;
450 }
451 }
452 }
453 if (issueAIndex > issueBIndex) {
454 return -1;
455 } else if (issueAIndex < issueBIndex) {
456 return 1;
457 }
458 }
459
460 return 0;
461 }
462
463 public static String getResolutionName(int value) {
464 return getResolutionName(value, ITrackerResources.getLocale());
465 }
466
467 public static String getResolutionName(int value, Locale locale) {
468 return getResolutionName(Integer.toString(value), locale);
469 }
470
471 public static String getResolutionName(String value, Locale locale) {
472 return ITrackerResources.getString(
473 ITrackerResources.KEY_BASE_RESOLUTION + value, locale);
474 }
475
476 public static String checkResolutionName(String value, Locale locale)
477 throws MissingResourceException {
478 return ITrackerResources.getCheckForKey(
479 ITrackerResources.KEY_BASE_RESOLUTION + value, locale);
480 }
481
482
483
484
485
486
487
488
489
490
491
492 public static List<NameValuePair> getResolutions(Locale locale) {
493 NameValuePair[] resolutionStrings = new NameValuePair[resolutions
494 .size()];
495 for (int i = 0; i < resolutions.size(); i++) {
496 resolutionStrings[i] = new NameValuePair(ITrackerResources
497 .getString(ITrackerResources.KEY_BASE_RESOLUTION
498 + resolutions.get(i).getValue(), locale),
499 resolutions.get(i).getValue());
500 }
501 return Arrays.asList(resolutionStrings);
502 }
503
504
505
506
507 public static void setResolutions(List<Configuration> value) {
508 resolutions = (value == null ? new ArrayList<Configuration>() : value);
509 }
510
511 public static String getActivityName(IssueActivityType type) {
512 return getActivityName(type, ITrackerResources.getLocale());
513 }
514
515 public static String getActivityName(IssueActivityType type, Locale locale) {
516 return ITrackerResources.getString("itracker.activity."
517 + String.valueOf(type.name()), locale);
518 }
519
520
521
522
523
524
525 public static List<CustomField> getCustomFields() {
526 return (customFields == null ? new ArrayList<CustomField>()
527 : customFields);
528 }
529
530
531
532
533
534
535 public static void setCustomFields(List<CustomField> value) {
536 customFields = (value == null ? new ArrayList<CustomField>() : value);
537 }
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571 public static CustomField getCustomField(Integer id) {
572 return getCustomField(id, ITrackerResources.getLocale());
573 }
574
575
576
577
578
579
580
581
582
583
584
585 public static CustomField getCustomField(Integer id, Locale locale) {
586 CustomField retField = null;
587
588 try {
589 for (int i = 0; i < customFields.size(); i++) {
590 if (customFields.get(i) != null
591 && customFields.get(i).getId() != null
592 && customFields.get(i).getId().equals(id)) {
593 retField = (CustomField) customFields.get(i).clone();
594 break;
595 }
596 }
597 } catch (CloneNotSupportedException cnse) {
598 logger.error("Error cloning CustomField: " + cnse.getMessage());
599 }
600 if (retField == null) {
601 retField = new CustomField();
602 }
603
604 return retField;
605 }
606
607
608
609
610 public static int getNumberCustomFields() {
611 return customFields.size();
612 }
613
614
615
616
617
618
619
620
621
622
623
624 public static boolean canViewIssue(Issue issue, User user,
625 Map<Integer, Set<PermissionType>> permissions) {
626 if (user == null) {
627 if (log.isInfoEnabled()) {
628 log
629 .info("canViewIssue: missing argument. user is null returning false");
630 }
631 return false;
632 }
633 return canViewIssue(issue, user.getId(), permissions);
634 }
635
636
637
638
639
640
641
642
643
644
645
646 public static boolean canViewIssue(Issue issue, Integer userId,
647 Map<Integer, Set<PermissionType>> permissions) {
648 if (issue == null || userId == null || permissions == null) {
649 if (log.isInfoEnabled()) {
650 log.info("canViewIssue: missing argument. issue: " + issue
651 + ", userid: " + userId + ", permissions: "
652 + permissions);
653 }
654 return false;
655 }
656
657 if (UserUtilities.hasPermission(permissions,
658 issue.getProject().getId(), PermissionType.ISSUE_VIEW_ALL
659 .getCode())) {
660 if (log.isInfoEnabled()) {
661 log.info("canViewIssue: issue: " + issue + ", user: " + userId
662 + ", permission: " + PermissionType.ISSUE_VIEW_ALL);
663 }
664 return true;
665 }
666
667
668
669
670 if (issue.getCreator().getId().equals(userId)) {
671 if (log.isInfoEnabled()) {
672 log.info("canViewIssue: issue: " + issue + ", user: " + userId
673 + ", permission: is creator");
674 }
675 return true;
676 }
677
678 if (issue.getOwner() != null) {
679 if (issue.getOwner().getId().equals(userId)) {
680
681 if (log.isInfoEnabled()) {
682 log.info("canViewIssue: issue: " + issue + ", user: "
683 + userId + ", permission: is owner");
684 }
685 return true;
686 }
687 }
688
689 if (!UserUtilities.hasPermission(permissions, issue.getProject()
690 .getId(), PermissionType.ISSUE_VIEW_USERS.getCode())) {
691 if (log.isInfoEnabled()) {
692 log.info("canViewIssue: issue: " + issue + ", user: " + userId
693 + ", permission: " + PermissionType.ISSUE_VIEW_USERS);
694 }
695
696 return false;
697 }
698
699 if (log.isInfoEnabled()) {
700 log.info("canViewIssue: issue: " + issue + ", user: " + userId
701 + ", permission: none matched");
702 }
703 return false;
704 }
705
706
707
708
709
710
711
712
713
714
715
716 public static boolean canEditIssue(Issue issue, Integer userId,
717 Map<Integer, Set<PermissionType>> permissions) {
718 if (issue == null || userId == null || permissions == null) {
719 if (log.isInfoEnabled()) {
720 log.info("canEditIssue: missing argument. issue: " + issue
721 + ", userid: " + userId + ", permissions: "
722 + permissions);
723 }
724 return false;
725 }
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742 if (UserUtilities.hasPermission(permissions,
743 issue.getProject().getId(), PermissionType.ISSUE_EDIT_ALL
744 .getCode())) {
745
746 if (log.isDebugEnabled()) {
747 log.debug("canEditIssue: user " + userId
748 + " has permission to edit issue " + issue.getId()
749 + ":" + PermissionType.ISSUE_EDIT_ALL);
750 }
751 return true;
752 }
753 if (!UserUtilities.hasPermission(permissions, issue.getProject()
754 .getId(), PermissionType.ISSUE_EDIT_USERS.getCode())) {
755 if (log.isDebugEnabled()) {
756 log.debug("canEditIssue: user " + userId
757 + " has not permission to edit issue " + issue.getId()
758 + ":" + PermissionType.ISSUE_EDIT_USERS);
759 }
760 return false;
761 }
762
763 if (issue.getCreator().getId().equals(userId)) {
764 if (log.isDebugEnabled()) {
765 log.debug("canEditIssue: user " + userId
766 + " is creator of issue " + issue.getId() + ":");
767 }
768 return true;
769 }
770 if (issue.getOwner() != null) {
771 if (issue.getOwner().getId().equals(userId)) {
772 if (log.isDebugEnabled()) {
773 log.debug("canEditIssue: user " + userId
774 + " is owner of issue " + issue.getId() + ":");
775 }
776 return true;
777 }
778 }
779
780 if (log.isDebugEnabled()) {
781 log.debug("canEditIssue: user " + userId
782 + " could not match permission, denied");
783 }
784 return false;
785 }
786
787
788
789
790
791
792
793
794
795
796
797 public static boolean canBeAssignedIssue(Issue issue, Integer userId,
798 Map<Integer, Set<PermissionType>> permissions) {
799 if (issue == null || userId == null || permissions == null) {
800 return false;
801 }
802
803 if (UserUtilities.hasPermission(permissions,
804 issue.getProject().getId(), PermissionType.ISSUE_EDIT_ALL
805 .getCode())) {
806 return true;
807 }
808 if (UserUtilities.hasPermission(permissions,
809 issue.getProject().getId(), PermissionType.ISSUE_EDIT_USERS
810 .getCode())) {
811 if (issue.getCreator().getId().equals(userId)) {
812 return true;
813 } else if (UserUtilities.hasPermission(permissions, issue
814 .getProject().getId(), PermissionType.ISSUE_ASSIGNABLE
815 .getCode())) {
816 return true;
817 } else if (issue.getOwner().getId() != null
818 && issue.getOwner().getId().equals(userId)) {
819 return true;
820 }
821 }
822
823 return false;
824 }
825
826
827
828
829
830
831
832
833
834
835
836 public static boolean canUnassignIssue(Issue issue, Integer userId,
837 Map<Integer, Set<PermissionType>> permissions) {
838 if (issue == null || userId == null || permissions == null) {
839 return false;
840 }
841
842 if (UserUtilities.hasPermission(permissions,
843 issue.getProject().getId(), PermissionType.ISSUE_ASSIGN_OTHERS
844 .getCode())) {
845 return true;
846 }
847 if (issue.getOwner() != null
848 && userId.equals(issue.getOwner().getId())
849 && UserUtilities.hasPermission(permissions, issue.getProject()
850 .getId(), PermissionType.ISSUE_UNASSIGN_SELF.getCode())) {
851 return true;
852 }
853
854 return false;
855 }
856
857 public static boolean hasIssueRelation(Issue issue, Integer relatedIssueId) {
858 if (issue != null) {
859 List<IssueRelation> relations = issue.getRelations();
860 for (int i = 0; i < relations.size(); i++) {
861 if (relations.get(i).getRelatedIssue().getId().equals(
862 relatedIssueId)) {
863 return true;
864 }
865 }
866 }
867 return false;
868 }
869
870 public static boolean hasIssueNotification(Issue issue, Integer userId) {
871 return hasIssueNotification(issue, issue.getProject(), userId);
872 }
873
874
875
876
877
878
879
880
881
882
883 public static boolean hasIssueNotification(Issue issue, Project project,
884 Integer userId) {
885 if (issue == null || userId == null) {
886 return false;
887 }
888
889
890 if ((issue.getOwner() != null && issue.getOwner().getId().equals(userId))
891 || issue.getCreator().getId().equals(userId)) {
892 return true;
893 }
894
895 if (project != null && project.getOwners() != null && !project.getOwners().isEmpty()) {
896 Iterator<User> owners = project.getOwners().iterator();
897 while (owners.hasNext()) {
898 if (owners.next().getId().equals(userId)) {
899 return true;
900 }
901 }
902 }
903
904 Collection<Notification> notifications = ServletContextUtils.getItrackerServices().getNotificationService().getIssueNotifications(issue);
905 if (notifications != null && !notifications.isEmpty()) {
906 Iterator<Notification> notificationsIt = notifications.iterator();
907 while (notificationsIt.hasNext()) {
908 if (notificationsIt.next().getUser().getId().equals(userId)) {
909 return true;
910 }
911 }
912 }
913
914 return false;
915 }
916 }
917
918