1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.kpme.core.util;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.joda.time.*;
22 import org.kuali.kpme.core.api.KPMEConstants;
23 import org.kuali.kpme.core.api.assignment.Assignment;
24 import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey;
25 import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
26 import org.kuali.kpme.core.api.groupkey.HrGroupKey;
27 import org.kuali.kpme.core.api.util.KpmeUtils;
28 import org.kuali.kpme.core.service.HrServiceLocator;
29 import org.kuali.rice.core.api.config.property.ConfigContext;
30 import org.kuali.rice.core.api.util.RiceKeyConstants;
31 import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
32 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
33 import org.kuali.rice.krad.util.GlobalVariables;
34 import org.kuali.rice.krad.util.KRADConstants;
35
36 import javax.servlet.http.HttpServletRequest;
37 import java.math.BigDecimal;
38 import java.net.UnknownHostException;
39 import java.sql.Timestamp;
40 import java.util.*;
41
42 public class TKUtils {
43
44 private static final Logger LOG = Logger.getLogger(TKUtils.class);
45
46 public static boolean singleGroupKeyExists()
47 {
48 if (getSingleGroupKey() != null)
49 {
50 return true;
51 }
52 else
53 {
54 return false;
55 }
56 }
57
58
59 public static String getSingleGroupKey(LocalDate asOfDate)
60 {
61 String singleGroupKey = null;
62
63 List<? extends HrGroupKey> groupKeyList = HrServiceLocator.getHrGroupKeyService().getAllActiveHrGroupKeys(asOfDate);
64 if((CollectionUtils.isNotEmpty(groupKeyList)) && (groupKeyList.size() == 1)) {
65 singleGroupKey = groupKeyList.get(0).getGroupKeyCode();
66 }
67
68 return singleGroupKey;
69 }
70
71 public static String getSingleGroupKey()
72 {
73 return getSingleGroupKey(LocalDate.now());
74 }
75
76
77
78
79
80 public static String getDayOfMonthFromDateString(String dateString) {
81 String[] date = dateString.split("/");
82 return date[1];
83 }
84
85 public static String getSystemTimeZone() {
86 String configTimezone = TimeZone.getDefault().getID();
87 if (ConfigContext.getCurrentContextConfig() != null
88 && StringUtils.isNotBlank(ConfigContext.getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE).trim())) {
89 String tempTimeZoneId = ConfigContext.getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE);
90
91 if (TimeZone.getTimeZone(tempTimeZoneId) != null) {
92 configTimezone = ConfigContext.getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE);
93 } else {
94 LOG.error("Timezone set by configuration parameter " + KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE + " is not a valid time zone id. Using the systems default time zone instead.");
95 }
96 }
97
98
99 return configTimezone;
100 }
101
102 public static DateTimeZone getSystemDateTimeZone() {
103 return DateTimeZone.forID(TKUtils.getSystemTimeZone());
104 }
105
106 public static final LocalDate END_OF_TIME = new LocalDate(9999, 12, 31);
107
108 public static long getDaysBetween(LocalDate startDate, LocalDate endDate) {
109 long daysBetween = 0;
110
111 LocalDate currentDate = startDate;
112 while (currentDate.isBefore(endDate)) {
113 daysBetween++;
114 currentDate = currentDate.plusDays(1);
115 }
116
117 return daysBetween;
118 }
119
120 public static BigDecimal getHoursBetween(long start, long end) {
121 long diff = end - start;
122 BigDecimal hrsReminder = new BigDecimal((diff / 3600000.0) % 24);
123
124 if (hrsReminder.compareTo(BigDecimal.ZERO) == 0 && diff > 0) {
125 return new BigDecimal(diff / 3600000.0).setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING).abs();
126 }
127 return hrsReminder.setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING).abs();
128 }
129
130 public static BigDecimal getMinutesBetween(DateTime start, DateTime end) {
131 long diff = end.getMillis() - start.getMillis();
132 BigDecimal hrsReminder = new BigDecimal((diff / 3600000.0) % 24);
133
134 if (hrsReminder.compareTo(BigDecimal.ZERO) == 0 && diff > 0) {
135 return new BigDecimal(diff / 60000.0).setScale(0, HrConstants.BIG_DECIMAL_SCALE_ROUNDING).abs();
136 }
137 BigDecimal min = new BigDecimal((diff / 60000.0));
138 return min.setScale(0, HrConstants.BIG_DECIMAL_SCALE_ROUNDING).abs();
139 }
140
141 public static BigDecimal getHoursFromMinutes(BigDecimal minutes) {
142 if (minutes == null) {
143 return null;
144 }
145 return minutes.divide(BigDecimal.valueOf(60), HrConstants.MATH_CONTEXT).setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING);
146 }
147
148
149 public static Map<String, String> formatAssignmentDescription(Assignment assignment) {
150 Map<String, String> assignmentDescriptions = new LinkedHashMap<String, String>();
151
152 String assignmentDescKey = KpmeUtils.formatAssignmentKey(assignment.getGroupKeyCode(), assignment.getJobNumber(), assignment.getWorkArea(), assignment.getTask());
153 String assignmentDescValue = HrServiceLocator.getAssignmentService().getAssignmentDescription(assignment.getPrincipalId(), assignment.getGroupKeyCode(), assignment.getJobNumber(), assignment.getWorkArea(), assignment.getTask(), assignment.getEffectiveLocalDate());
154 assignmentDescriptions.put(assignmentDescKey, assignmentDescValue);
155
156 return assignmentDescriptions;
157 }
158
159
160
161
162
163
164
165
166
167 public static List<Interval> getDaySpanForCalendarEntry(CalendarEntry calendarEntry, DateTimeZone timeZone) {
168 DateTime beginDateTime = calendarEntry.getBeginPeriodLocalDateTime().toDateTime(timeZone);
169 DateTime endDateTime = calendarEntry.getEndPeriodLocalDateTime().toDateTime(timeZone);
170
171 List<Interval> dayIntervals = new ArrayList<Interval>();
172
173 DateTime currDateTime = beginDateTime;
174 while (currDateTime.isBefore(endDateTime)) {
175 DateTime prevDateTime = currDateTime;
176 currDateTime = currDateTime.plusDays(1);
177 Interval daySpan = new Interval(prevDateTime, currDateTime);
178 dayIntervals.add(daySpan);
179 }
180
181 return dayIntervals;
182 }
183
184 public static long convertHoursToMillis(BigDecimal hours) {
185 return hours.multiply(HrConstants.BIG_DECIMAL_MS_IN_H, HrConstants.MATH_CONTEXT).longValue();
186 }
187
188 public static BigDecimal convertMillisToHours(long millis) {
189 return (new BigDecimal(millis)).divide(HrConstants.BIG_DECIMAL_MS_IN_H, HrConstants.MATH_CONTEXT);
190 }
191
192 public static BigDecimal convertMillisToMinutes(long millis) {
193 return (new BigDecimal(millis)).divide(HrConstants.BIG_DECIMAL_MS_IN_M, HrConstants.MATH_CONTEXT);
194 }
195
196 public static BigDecimal convertMillisToDays(long millis) {
197 BigDecimal hrs = convertMillisToHours(millis);
198 return hrs.divide(HrConstants.BIG_DECIMAL_HRS_IN_DAY, HrConstants.MATH_CONTEXT);
199 }
200
201 public static BigDecimal convertMinutesToHours(BigDecimal minutes) {
202 return minutes.divide(HrConstants.BIG_DECIMAL_60, HrConstants.MATH_CONTEXT);
203 }
204
205 public static int convertMillisToWholeDays(long millis) {
206 BigDecimal days = convertMillisToDays(millis);
207 return Integer.parseInt(days.setScale(0, BigDecimal.ROUND_UP).toString());
208 }
209
210
211
212
213
214 public static boolean isVirtualWorkDay(DateTime beginPeriodDateTime) {
215 return (beginPeriodDateTime.getHourOfDay() != 0 || beginPeriodDateTime.getMinuteOfHour() != 0
216 && beginPeriodDateTime.get(DateTimeFieldType.halfdayOfDay()) != DateTimeConstants.AM);
217 }
218
219
220
221
222
223
224
225
226
227
228 public static DateTime convertDateStringToDateTime(String dateStr, String timeStr) {
229
230 String[] date = dateStr.split("/");
231 String[] time = timeStr.split(":");
232
233 DateTimeZone dtz = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getTargetUserTimezone());
234
235
236
237
238
239 DateTime dateTime = new DateTime(
240 Integer.parseInt(date[2]),
241 Integer.parseInt(date[0]),
242 Integer.parseInt(date[1]),
243 Integer.parseInt(time[0]),
244 Integer.parseInt(time[1]),
245 0, 0, dtz);
246
247 return dateTime;
248 }
249
250 public static DateTime convertDateStringToDateTimeWithTimeZone(String dateStr, String timeStr, DateTimeZone dtz) {
251
252 String[] date = dateStr.split("/");
253 String[] time = timeStr.split(":");
254
255
256
257
258
259 DateTime dateTime = new DateTime(
260 Integer.parseInt(date[2]),
261 Integer.parseInt(date[0]),
262 Integer.parseInt(date[1]),
263 Integer.parseInt(time[0]),
264 Integer.parseInt(time[1]),
265 0, 0, dtz);
266
267 return dateTime;
268 }
269
270 public static DateTime convertDateStringToDateTimeWithoutZone(String dateStr, String timeStr) {
271
272 String[] date = dateStr.split("/");
273 String[] time = timeStr.split(":");
274
275
276
277
278
279 DateTime dateTime = new DateTime(
280 Integer.parseInt(date[2]),
281 Integer.parseInt(date[0]),
282 Integer.parseInt(date[1]),
283 Integer.parseInt(time[0]),
284 Integer.parseInt(time[1]),
285 0, 0);
286
287 return dateTime;
288 }
289
290 public static String getIPAddressFromRequest(String remoteAddress) {
291
292
293 if (remoteAddress.indexOf(':') > -1) {
294 LOG.warn("ignoring IPv6 address for clock-in: " + remoteAddress);
295 remoteAddress = "";
296 }
297
298 return remoteAddress;
299 }
300
301 public static String getIPNumber() {
302 try {
303 return java.net.InetAddress.getLocalHost().getHostAddress();
304 } catch (UnknownHostException e) {
305 return "unknown";
306 }
307 }
308
309 public static String getIPAddressFromRequest(HttpServletRequest request) {
310
311
312 String fwdIp = request.getHeader("X-Forwarded-For");
313 if (fwdIp != null) {
314 LOG.info("Forwarded IP: " + fwdIp);
315 return fwdIp;
316 }
317
318 String ip = request.getRemoteAddr();
319 if (ip.indexOf(':') > -1) {
320 LOG.warn("ignoring IPv6 address for clock-in: " + ip);
321 ip = "";
322 }
323
324 return ip;
325 }
326
327
328 public static Timestamp subtractOneSecondFromTimestamp(Timestamp originalTimestamp) {
329 DateTime dt = new DateTime(originalTimestamp);
330 dt = dt.minusSeconds(1);
331 return new Timestamp(dt.getMillis());
332 }
333
334 public static String formatDate(LocalDate localDate) {
335 if (localDate == null) {
336 return StringUtils.EMPTY;
337 }
338 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.print(localDate);
339 }
340
341 public static String formatDateTimeShort(DateTime dateTime) {
342 if (dateTime == null) {
343 return StringUtils.EMPTY;
344 }
345 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.print(dateTime);
346 }
347
348 public static String formatDateTimeLong(DateTime dateTime){
349 if (dateTime == null) {
350 return StringUtils.EMPTY;
351 }
352 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT_WITH_SEC.print(dateTime);
353 }
354
355 public static String formatDateTimeWithTZ(DateTime dateTime){
356 if (dateTime == null) {
357 return StringUtils.EMPTY;
358 }
359 return HrConstants.DateTimeFormats.FULL_DATE_WITH_TZ.print(dateTime);
360 }
361
362 public static LocalDate formatDateString(String date){
363 if (StringUtils.isEmpty(date)) {
364 return null;
365 }
366 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.parseLocalDate(date);
367 }
368
369 public static String formatTimeShort(String dateString) {
370 if (StringUtils.isEmpty(dateString)) {
371 return null;
372 }
373 DateTime tempDate = HrConstants.DateTimeFormats.BASIC_DATE_FORMAT_WITH_SEC.parseDateTime(dateString);
374 return HrConstants.DateTimeFormats.BASIC_TIME_FORMAT.print(tempDate);
375 }
376
377 public static DateTime formatDateTimeString(String dateTime) {
378 if (StringUtils.isEmpty(dateTime)) {
379 return null;
380 }
381 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.parseDateTime(dateTime).withZone(HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback());
382 }
383
384 public static DateTime formatDateTimeStringNoTimezone(String dateTime) {
385 if (StringUtils.isEmpty(dateTime)) {
386 return null;
387 }
388 try {
389 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.parseDateTime(dateTime);
390 } catch (IllegalArgumentException e) {
391 return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT_WITH_SEC.parseDateTime(dateTime);
392 }
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406 public static String getTimezoneOffset(DateTime date) {
407 StringBuilder o = new StringBuilder();
408
409 int offsetms = date.getZone().getOffset(date);
410 boolean negative = offsetms < 0;
411 if (negative) offsetms = offsetms * -1;
412
413 Period period = new Period(offsetms);
414 if (negative) o.append('-');
415 o.append(StringUtils.leftPad(period.getHours() + "", 2, '0'));
416 o.append(StringUtils.leftPad(period.getMinutes() + "", 2, '0'));
417
418 return o.toString();
419 }
420
421 public static String arrayToString(String[] stringArray) {
422 StringBuilder str = new StringBuilder();
423 for (String string : stringArray) {
424 str.append(string);
425 }
426 return str.toString();
427 }
428
429
430
431
432 public static int getSessionTimeoutTime() {
433 return StringUtils.isBlank(ConfigContext.getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.SESSION_TIMEOUT))
434 ? 2700 :
435 Integer.parseInt(ConfigContext.getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.SESSION_TIMEOUT));
436 }
437
438 public static Timestamp getCurrentTimestamp() {
439 return new Timestamp(System.currentTimeMillis());
440 }
441
442 public static List<Interval> createDaySpan(DateTime beginDateTime, DateTime endDateTime, DateTimeZone zone) {
443 beginDateTime = beginDateTime.toDateTime(zone);
444 endDateTime = endDateTime.toDateTime(zone);
445 List<Interval> dayIntervals = new ArrayList<Interval>();
446
447 DateTime currDateTime = beginDateTime;
448 while (currDateTime.isBefore(endDateTime)) {
449 DateTime prevDateTime = currDateTime;
450 currDateTime = currDateTime.plusDays(1);
451 Interval daySpan = new Interval(prevDateTime, currDateTime);
452 dayIntervals.add(daySpan);
453 }
454
455 return dayIntervals;
456 }
457
458 public static List<Interval> getDaySpanForCalendarEntry(CalendarEntry calendarEntry) {
459 return getDaySpanForCalendarEntry(calendarEntry, HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback());
460 }
461
462 public static List<Interval> getFullWeekDaySpanForCalendarEntry(CalendarEntry calendarEntry) {
463 return getFullWeekDaySpanForCalendarEntry(calendarEntry, HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback());
464 }
465
466 public static List<Interval> getFullWeekDaySpanForCalendarEntry(CalendarEntry calendarEntry, DateTimeZone timeZone) {
467 DateTime beginDateTime = calendarEntry.getBeginPeriodLocalDateTime().toDateTime(timeZone);
468 DateTime endDateTime = calendarEntry.getEndPeriodLocalDateTime().toDateTime(timeZone);
469
470 List<Interval> dayIntervals = new ArrayList<Interval>();
471
472 DateTime currDateTime = beginDateTime;
473 if (beginDateTime.getDayOfWeek() != 7) {
474 currDateTime = beginDateTime.plusDays(0 - beginDateTime.getDayOfWeek());
475 }
476
477 int afterEndDate = 6 - endDateTime.getDayOfWeek();
478 if (endDateTime.getDayOfWeek() == 7 && endDateTime.getHourOfDay() != 0) {
479 afterEndDate = 6;
480 }
481 if (endDateTime.getHourOfDay() == 0) {
482 afterEndDate += 1;
483 }
484 DateTime aDate = endDateTime.plusDays(afterEndDate);
485 while (currDateTime.isBefore(aDate)) {
486 DateTime prevDateTime = currDateTime;
487 currDateTime = currDateTime.plusDays(1);
488 Interval daySpan = new Interval(prevDateTime, currDateTime);
489 dayIntervals.add(daySpan);
490 }
491
492 return dayIntervals;
493 }
494
495 public static int getWorkDays(DateTime startDate, DateTime endDate) {
496 int workDays = 0;
497
498 DateTime currentDate = startDate;
499 while (!currentDate.isAfter(endDate)) {
500 if (!isWeekend(currentDate)) {
501 workDays++;
502 }
503 currentDate = currentDate.plusDays(1);
504 }
505
506 return workDays;
507 }
508
509 public static boolean isWeekend(DateTime date) {
510 return date.getDayOfWeek() == DateTimeConstants.SATURDAY || date.getDayOfWeek() == DateTimeConstants.SUNDAY;
511 }
512
513
514
515
516
517
518
519
520
521 public static String getFromDateString(String dateString) {
522 String fromDateString = StringUtils.EMPTY;
523
524 if (StringUtils.startsWith(dateString, ">=")) {
525 fromDateString = StringUtils.substringAfter(dateString, ">=");
526 } else if (StringUtils.contains(dateString, "..")) {
527 fromDateString = StringUtils.substringBefore(dateString, "..");
528 }
529
530 return fromDateString;
531 }
532
533
534
535
536
537
538
539
540
541 public static String getToDateString(String dateString) {
542 String toDateString = StringUtils.EMPTY;
543
544 if (StringUtils.startsWith(dateString, "<=")) {
545 toDateString = StringUtils.substringAfter(dateString, "<=");
546 } else if (StringUtils.contains(dateString, "..")) {
547 toDateString = StringUtils.substringAfter(dateString, "..");
548 }
549
550 return toDateString;
551 }
552
553
554 public static boolean isDateEqualOrBetween(DateTime date, String searchDateString) {
555 boolean valid = false;
556
557 String fromDateString = TKUtils.getFromDateString(searchDateString);
558 DateTime fromDate = TKUtils.formatDateTimeString(fromDateString);
559 String toDateString = TKUtils.getToDateString(searchDateString);
560 DateTime toDate = TKUtils.formatDateTimeString(toDateString);
561
562 if (date != null) {
563
564 if (fromDate != null ? (date.isEqual(fromDate) || date.isAfter(fromDate)) :
565 toDate != null ? (date.isBefore(toDate) || date.isEqual(toDate)) : true) {
566 valid = true;
567 }
568 }
569
570 return valid;
571 }
572
573 public static String getRandomColor(Set<String> randomColors) {
574 String[] letters = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F".split(",");
575 String color = "#";
576 for (int i = 0; i < 6; i++) {
577 int index = (int) Math.round(Math.random() * 15);
578 color += letters[index];
579 }
580 if (randomColors.contains(color)) {
581 color = getRandomColor(randomColors);
582 }
583 return color;
584 }
585
586
587
588
589 public static BigDecimal cleanNumeric( String value ) {
590 String cleanedValue = value.replaceAll( "[^-0-9.]", "" );
591
592 if ( cleanedValue.lastIndexOf( '-' ) > 0 ) {
593 if ( cleanedValue.charAt( 0 ) == '-' ) {
594 cleanedValue = "-" + cleanedValue.replaceAll( "-", "" );
595 } else {
596 cleanedValue = cleanedValue.replaceAll( "-", "" );
597 }
598 }
599
600 int decimalLoc = cleanedValue.lastIndexOf( '.' );
601 if ( cleanedValue.indexOf( '.' ) != decimalLoc ) {
602 cleanedValue = cleanedValue.substring( 0, decimalLoc ).replaceAll( "\\.", "" ) + cleanedValue.substring( decimalLoc );
603 }
604 try {
605 return new BigDecimal( cleanedValue );
606 } catch ( NumberFormatException ex ) {
607 GlobalVariables.getMessageMap().putError(KRADConstants.DOCUMENT_ERRORS, RiceKeyConstants.ERROR_CUSTOM, new String[] { "Invalid Numeric Input: " + value });
608 return null;
609 }
610 }
611
612 public static String getDocumentDescription(String principalId, LocalDate effectiveDate) {
613 StringBuffer docDescription = new StringBuffer();
614 EntityNamePrincipalName principalName = null;
615 if (principalId != null) {
616 principalName = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
617 }
618 String personName = (principalName != null && principalName.getDefaultName() != null) ? principalName.getDefaultName().getCompositeName() : StringUtils.EMPTY;
619 String date = TKUtils.formatDate(effectiveDate);
620 docDescription.append(personName + " (" + principalId + ") - " + date);
621 return docDescription.toString();
622 }
623
624
625
626
627
628 public static DateTime convertTimeForDifferentTimeZone(DateTime aDateTime, DateTimeZone fromTimeZone, DateTimeZone toTimeZone) {
629 if(fromTimeZone == null || toTimeZone == null || fromTimeZone.equals(toTimeZone))
630 return aDateTime;
631
632 Long millisOfSysTime = fromTimeZone.getMillisKeepLocal(toTimeZone, aDateTime.getMillis());
633 DateTime toTime = new DateTime(millisOfSysTime);
634
635 return toTime;
636 }
637
638 public static DateTime convertDateTimeToDifferentTimezone(DateTime aDateTime, DateTimeZone fromTimeZone, DateTimeZone toTimeZone) {
639 if(fromTimeZone == null || toTimeZone == null || fromTimeZone.equals(toTimeZone))
640 return aDateTime;
641
642 Long millisOfSysTime = toTimeZone.getMillisKeepLocal(fromTimeZone, aDateTime.getMillis());
643 DateTime toTime = new DateTime(millisOfSysTime);
644
645 return toTime;
646 }
647
648
649 public static Assignment getAssignmentWithKey(List<Assignment> assignments, AssignmentDescriptionKey assignmentDescriptionKey) {
650
651 for (Assignment assignment : assignments) {
652 if (StringUtils.equals(assignment.getGroupKeyCode(), assignmentDescriptionKey.getGroupKeyCode()) &&
653 assignment.getJobNumber().compareTo(assignmentDescriptionKey.getJobNumber()) == 0 &&
654 assignment.getWorkArea().compareTo(assignmentDescriptionKey.getWorkArea()) == 0 &&
655 assignment.getTask().compareTo(assignmentDescriptionKey.getTask()) == 0) {
656 return assignment;
657 }
658 }
659
660 return null;
661 }
662
663
664
665 }