Java tutorial
/** * Copyright 2004-2014 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl2.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.kpme.core.util; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.joda.time.*; import org.kuali.kpme.core.api.KPMEConstants; import org.kuali.kpme.core.api.assignment.Assignment; import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey; import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; import org.kuali.kpme.core.api.groupkey.HrGroupKey; import org.kuali.kpme.core.api.util.KpmeUtils; import org.kuali.kpme.core.service.HrServiceLocator; import org.kuali.rice.core.api.config.property.ConfigContext; import org.kuali.rice.core.api.util.RiceKeyConstants; import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.net.UnknownHostException; import java.sql.Timestamp; import java.util.*; public class TKUtils { private static final Logger LOG = Logger.getLogger(TKUtils.class); public static boolean singleGroupKeyExists() { if (getSingleGroupKey() != null) { return true; } else { return false; } } public static String getSingleGroupKey(LocalDate asOfDate) { String singleGroupKey = null; List<? extends HrGroupKey> groupKeyList = HrServiceLocator.getHrGroupKeyService() .getAllActiveHrGroupKeys(asOfDate); if ((CollectionUtils.isNotEmpty(groupKeyList)) && (groupKeyList.size() == 1)) { singleGroupKey = groupKeyList.get(0).getGroupKeyCode(); } return singleGroupKey; } public static String getSingleGroupKey() { return getSingleGroupKey(LocalDate.now()); } /** * @param dateString the format has to be mm/dd/yyyy * @return dayOfMonth */ public static String getDayOfMonthFromDateString(String dateString) { String[] date = dateString.split("/"); return date[1]; } public static String getSystemTimeZone() { String configTimezone = TimeZone.getDefault().getID(); if (ConfigContext.getCurrentContextConfig() != null && StringUtils.isNotBlank(ConfigContext .getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE).trim())) { String tempTimeZoneId = ConfigContext.getCurrentContextConfig() .getProperty(KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE); if (TimeZone.getTimeZone(tempTimeZoneId) != null) { configTimezone = ConfigContext.getCurrentContextConfig() .getProperty(KPMEConstants.ConfigSettings.KPME_SYSTEM_TIMEZONE); } else { 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."); } } return configTimezone; } public static DateTimeZone getSystemDateTimeZone() { return DateTimeZone.forID(TKUtils.getSystemTimeZone()); } public static final LocalDate END_OF_TIME = new LocalDate(9999, 12, 31); public static long getDaysBetween(LocalDate startDate, LocalDate endDate) { long daysBetween = 0; LocalDate currentDate = startDate; while (currentDate.isBefore(endDate)) { daysBetween++; currentDate = currentDate.plusDays(1); } return daysBetween; } public static BigDecimal getHoursBetween(long start, long end) { long diff = end - start; BigDecimal hrsReminder = new BigDecimal((diff / 3600000.0) % 24); // if the hours is exact duplicate of 24 hours if (hrsReminder.compareTo(BigDecimal.ZERO) == 0 && diff > 0) { return new BigDecimal(diff / 3600000.0) .setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING).abs(); } return hrsReminder.setScale(HrConstants.BIG_DECIMAL_SCALE, HrConstants.BIG_DECIMAL_SCALE_ROUNDING).abs(); } public static Map<String, String> formatAssignmentDescription(Assignment assignment) { Map<String, String> assignmentDescriptions = new LinkedHashMap<String, String>(); String assignmentDescKey = KpmeUtils.formatAssignmentKey(assignment.getGroupKeyCode(), assignment.getJobNumber(), assignment.getWorkArea(), assignment.getTask()); String assignmentDescValue = HrServiceLocator.getAssignmentService().getAssignmentDescription( assignment.getPrincipalId(), assignment.getGroupKeyCode(), assignment.getJobNumber(), assignment.getWorkArea(), assignment.getTask(), assignment.getEffectiveLocalDate()); assignmentDescriptions.put(assignmentDescKey, assignmentDescValue); return assignmentDescriptions; } /** * Constructs a list of Day Spans for the pay calendar entry provided. You * must also provide a DateTimeZone so that we can create relative boundaries. * * @param calendarEntry * @param timeZone * @return */ public static List<Interval> getDaySpanForCalendarEntry(CalendarEntry calendarEntry, DateTimeZone timeZone) { DateTime beginDateTime = calendarEntry.getBeginPeriodLocalDateTime().toDateTime(timeZone); DateTime endDateTime = calendarEntry.getEndPeriodLocalDateTime().toDateTime(timeZone); List<Interval> dayIntervals = new ArrayList<Interval>(); DateTime currDateTime = beginDateTime; while (currDateTime.isBefore(endDateTime)) { DateTime prevDateTime = currDateTime; currDateTime = currDateTime.plusDays(1); Interval daySpan = new Interval(prevDateTime, currDateTime); dayIntervals.add(daySpan); } return dayIntervals; } public static long convertHoursToMillis(BigDecimal hours) { return hours.multiply(HrConstants.BIG_DECIMAL_MS_IN_H, HrConstants.MATH_CONTEXT).longValue(); } public static BigDecimal convertMillisToHours(long millis) { return (new BigDecimal(millis)).divide(HrConstants.BIG_DECIMAL_MS_IN_H, HrConstants.MATH_CONTEXT); } public static BigDecimal convertMillisToMinutes(long millis) { return (new BigDecimal(millis)).divide(HrConstants.BIG_DECIMAL_MS_IN_M, HrConstants.MATH_CONTEXT); } public static BigDecimal convertMillisToDays(long millis) { BigDecimal hrs = convertMillisToHours(millis); return hrs.divide(HrConstants.BIG_DECIMAL_HRS_IN_DAY, HrConstants.MATH_CONTEXT); } public static BigDecimal convertMinutesToHours(BigDecimal minutes) { return minutes.divide(HrConstants.BIG_DECIMAL_60, HrConstants.MATH_CONTEXT); } public static int convertMillisToWholeDays(long millis) { BigDecimal days = convertMillisToDays(millis); return Integer.parseInt(days.setScale(0, BigDecimal.ROUND_UP).toString()); } /* * Compares and confirms if the start of the day is at midnight or on a virtual day boundary * returns true if at midnight false otherwise(assuming 24 hr days) */ public static boolean isVirtualWorkDay(DateTime beginPeriodDateTime) { return (beginPeriodDateTime.getHourOfDay() != 0 || beginPeriodDateTime.getMinuteOfHour() != 0 && beginPeriodDateTime.get(DateTimeFieldType.halfdayOfDay()) != DateTimeConstants.AM); } /** * Creates a Timestamp object using Jodatime as an intermediate data structure * from the provided date and time string. (From the form POST and javascript * formats) * * @param dateStr (the format is 01/01/2011) * @param timeStr (the format is 8:0) * @return Timestamp */ public static DateTime convertDateStringToDateTime(String dateStr, String timeStr) { // the date/time format is defined in tk.calendar.js. For now, the format is 11/17/2010 8:0 String[] date = dateStr.split("/"); String[] time = timeStr.split(":"); DateTimeZone dtz = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getTargetUserTimezone()); // this is from the jodattime javadoc: // DateTime(int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond, DateTimeZone zone) // Noted that the month value is the actual month which is different than the java date object where the month value is the current month minus 1. // I tried to use the actual month in the code as much as I can to reduce the convertions. DateTime dateTime = new DateTime(Integer.parseInt(date[2]), Integer.parseInt(date[0]), Integer.parseInt(date[1]), Integer.parseInt(time[0]), Integer.parseInt(time[1]), 0, 0, dtz); return dateTime; } public static DateTime convertDateStringToDateTimeWithTimeZone(String dateStr, String timeStr, DateTimeZone dtz) { // the date/time format is defined in tk.calendar.js. For now, the format is 11/17/2010 8:0 String[] date = dateStr.split("/"); String[] time = timeStr.split(":"); // this is from the jodattime javadoc: // DateTime(int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond, DateTimeZone zone) // Noted that the month value is the actual month which is different than the java date object where the month value is the current month minus 1. // I tried to use the actual month in the code as much as I can to reduce the convertions. DateTime dateTime = new DateTime(Integer.parseInt(date[2]), Integer.parseInt(date[0]), Integer.parseInt(date[1]), Integer.parseInt(time[0]), Integer.parseInt(time[1]), 0, 0, dtz); return dateTime; } public static DateTime convertDateStringToDateTimeWithoutZone(String dateStr, String timeStr) { // the date/time format is defined in tk.calendar.js. For now, the format is 11/17/2010 8:0 String[] date = dateStr.split("/"); String[] time = timeStr.split(":"); // this is from the jodattime javadoc: // DateTime(int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond, DateTimeZone zone) // Noted that the month value is the actual month which is different than the java date object where the month value is the current month minus 1. // I tried to use the actual month in the code as much as I can to reduce the convertions. DateTime dateTime = new DateTime(Integer.parseInt(date[2]), Integer.parseInt(date[0]), Integer.parseInt(date[1]), Integer.parseInt(time[0]), Integer.parseInt(time[1]), 0, 0); return dateTime; } public static String getIPAddressFromRequest(String remoteAddress) { // Check for IPv6 addresses - Not sure what to do with them at this point. // TODO: IPv6 - I see these on my local machine. if (remoteAddress.indexOf(':') > -1) { LOG.warn("ignoring IPv6 address for clock-in: " + remoteAddress); remoteAddress = ""; } return remoteAddress; } public static String getIPNumber() { try { return java.net.InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { return "unknown"; } } public static String getIPAddressFromRequest(HttpServletRequest request) { // Check for IPv6 addresses - Not sure what to do with them at this point. // TODO: IPv6 - I see these on my local machine. String fwdIp = request.getHeader("X-Forwarded-For"); if (fwdIp != null) { LOG.info("Forwarded IP: " + fwdIp); return fwdIp; } String ip = request.getRemoteAddr(); if (ip.indexOf(':') > -1) { LOG.warn("ignoring IPv6 address for clock-in: " + ip); ip = ""; } return ip; } //Used to preserve active row fetching based on max(timestamp) public static Timestamp subtractOneSecondFromTimestamp(Timestamp originalTimestamp) { DateTime dt = new DateTime(originalTimestamp); dt = dt.minusSeconds(1); return new Timestamp(dt.getMillis()); } public static String formatDate(LocalDate localDate) { if (localDate == null) { return StringUtils.EMPTY; } return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.print(localDate); } public static String formatDateTimeShort(DateTime dateTime) { if (dateTime == null) { return StringUtils.EMPTY; } return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.print(dateTime); } public static String formatDateTimeLong(DateTime dateTime) { if (dateTime == null) { return StringUtils.EMPTY; } return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT_WITH_SEC.print(dateTime); } public static LocalDate formatDateString(String date) { if (StringUtils.isEmpty(date)) { return null; } return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.parseLocalDate(date); } public static String formatTimeShort(String dateString) { if (StringUtils.isEmpty(dateString)) { return null; } DateTime tempDate = HrConstants.DateTimeFormats.BASIC_DATE_FORMAT_WITH_SEC.parseDateTime(dateString); return HrConstants.DateTimeFormats.BASIC_TIME_FORMAT.print(tempDate); } public static DateTime formatDateTimeString(String dateTime) { if (StringUtils.isEmpty(dateTime)) { return null; } return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.parseDateTime(dateTime) .withZone(HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback()); } public static DateTime formatDateTimeStringNoTimezone(String dateTime) { if (StringUtils.isEmpty(dateTime)) { return null; } try { return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT.parseDateTime(dateTime); } catch (IllegalArgumentException e) { return HrConstants.DateTimeFormats.BASIC_DATE_FORMAT_WITH_SEC.parseDateTime(dateTime); } } /** * Method to obtain the timezone offset string for the specified date time. * * Examples: * * -0500 * -0800 * * @param date * @return */ public static String getTimezoneOffset(DateTime date) { StringBuilder o = new StringBuilder(); int offsetms = date.getZone().getOffset(date); boolean negative = offsetms < 0; if (negative) offsetms = offsetms * -1; Period period = new Period(offsetms); if (negative) o.append('-'); o.append(StringUtils.leftPad(period.getHours() + "", 2, '0')); o.append(StringUtils.leftPad(period.getMinutes() + "", 2, '0')); return o.toString(); } public static String arrayToString(String[] stringArray) { StringBuilder str = new StringBuilder(); for (String string : stringArray) { str.append(string); } return str.toString(); } /** * Get the session timeout time. If it's not defined in the (local) config file, give it a default time. */ public static int getSessionTimeoutTime() { return StringUtils.isBlank( ConfigContext.getCurrentContextConfig().getProperty(KPMEConstants.ConfigSettings.SESSION_TIMEOUT)) ? 2700 : Integer.parseInt(ConfigContext.getCurrentContextConfig() .getProperty(KPMEConstants.ConfigSettings.SESSION_TIMEOUT)); } public static Timestamp getCurrentTimestamp() { return new Timestamp(System.currentTimeMillis()); } public static List<Interval> createDaySpan(DateTime beginDateTime, DateTime endDateTime, DateTimeZone zone) { beginDateTime = beginDateTime.toDateTime(zone); endDateTime = endDateTime.toDateTime(zone); List<Interval> dayIntervals = new ArrayList<Interval>(); DateTime currDateTime = beginDateTime; while (currDateTime.isBefore(endDateTime)) { DateTime prevDateTime = currDateTime; currDateTime = currDateTime.plusDays(1); Interval daySpan = new Interval(prevDateTime, currDateTime); dayIntervals.add(daySpan); } return dayIntervals; } public static List<Interval> getDaySpanForCalendarEntry(CalendarEntry calendarEntry) { return getDaySpanForCalendarEntry(calendarEntry, HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback()); } public static List<Interval> getFullWeekDaySpanForCalendarEntry(CalendarEntry calendarEntry) { return getFullWeekDaySpanForCalendarEntry(calendarEntry, HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback()); } public static List<Interval> getFullWeekDaySpanForCalendarEntry(CalendarEntry calendarEntry, DateTimeZone timeZone) { DateTime beginDateTime = calendarEntry.getBeginPeriodLocalDateTime().toDateTime(timeZone); DateTime endDateTime = calendarEntry.getEndPeriodLocalDateTime().toDateTime(timeZone); List<Interval> dayIntervals = new ArrayList<Interval>(); DateTime currDateTime = beginDateTime; if (beginDateTime.getDayOfWeek() != 7) { currDateTime = beginDateTime.plusDays(0 - beginDateTime.getDayOfWeek()); } int afterEndDate = 6 - endDateTime.getDayOfWeek(); if (endDateTime.getDayOfWeek() == 7 && endDateTime.getHourOfDay() != 0) { afterEndDate = 6; } if (endDateTime.getHourOfDay() == 0) { afterEndDate += 1; } DateTime aDate = endDateTime.plusDays(afterEndDate); while (currDateTime.isBefore(aDate)) { DateTime prevDateTime = currDateTime; currDateTime = currDateTime.plusDays(1); Interval daySpan = new Interval(prevDateTime, currDateTime); dayIntervals.add(daySpan); } return dayIntervals; } public static int getWorkDays(DateTime startDate, DateTime endDate) { int workDays = 0; DateTime currentDate = startDate; while (!currentDate.isAfter(endDate)) { if (!isWeekend(currentDate)) { workDays++; } currentDate = currentDate.plusDays(1); } return workDays; } public static boolean isWeekend(DateTime date) { return date.getDayOfWeek() == DateTimeConstants.SATURDAY || date.getDayOfWeek() == DateTimeConstants.SUNDAY; } /** * Returns effectiveDate "from" date that's passed in through dateString. * * The "from" dateString can either be from the format "fromDate..toDate" or ">=fromDate", otherwise an empty string is returned. * * @param dateString * @return */ public static String getFromDateString(String dateString) { String fromDateString = StringUtils.EMPTY; if (StringUtils.startsWith(dateString, ">=")) { fromDateString = StringUtils.substringAfter(dateString, ">="); } else if (StringUtils.contains(dateString, "..")) { fromDateString = StringUtils.substringBefore(dateString, ".."); } return fromDateString; } /** * Returns effectiveDate "to" date that's passed in through dateString. * * The "to" dateString can either be from the format "fromDate..toDate" or "<=toDate", otherwise an empty string is returned. * * @param dateString * @return */ public static String getToDateString(String dateString) { String toDateString = StringUtils.EMPTY; if (StringUtils.startsWith(dateString, "<=")) { toDateString = StringUtils.substringAfter(dateString, "<="); } else if (StringUtils.contains(dateString, "..")) { toDateString = StringUtils.substringAfter(dateString, ".."); } return toDateString; } public static boolean isDateEqualOrBetween(DateTime date, String searchDateString) { boolean valid = false; String fromDateString = TKUtils.getFromDateString(searchDateString); DateTime fromDate = TKUtils.formatDateTimeString(fromDateString); String toDateString = TKUtils.getToDateString(searchDateString); DateTime toDate = TKUtils.formatDateTimeString(toDateString); if (date != null) { if (fromDate != null ? (date.isEqual(fromDate) || date.isAfter(fromDate)) : toDate != null ? (date.isBefore(toDate) || date.isEqual(toDate)) : true) { valid = true; } } return valid; } public static String getRandomColor(Set<String> randomColors) { String[] letters = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F".split(","); String color = "#"; for (int i = 0; i < 6; i++) { int index = (int) Math.round(Math.random() * 15); color += letters[index]; } if (randomColors.contains(color)) { color = getRandomColor(randomColors); } return color; } /* * Cleans a numerical input so that it can be successfully used with lookups */ public static BigDecimal cleanNumeric(String value) { String cleanedValue = value.replaceAll("[^-0-9.]", ""); // ensure only one "minus" at the beginning, if any if (cleanedValue.lastIndexOf('-') > 0) { if (cleanedValue.charAt(0) == '-') { cleanedValue = "-" + cleanedValue.replaceAll("-", ""); } else { cleanedValue = cleanedValue.replaceAll("-", ""); } } // ensure only one decimal in the string int decimalLoc = cleanedValue.lastIndexOf('.'); if (cleanedValue.indexOf('.') != decimalLoc) { cleanedValue = cleanedValue.substring(0, decimalLoc).replaceAll("\\.", "") + cleanedValue.substring(decimalLoc); } try { return new BigDecimal(cleanedValue); } catch (NumberFormatException ex) { GlobalVariables.getMessageMap().putError(KRADConstants.DOCUMENT_ERRORS, RiceKeyConstants.ERROR_CUSTOM, new String[] { "Invalid Numeric Input: " + value }); return null; } } public static String getDocumentDescription(String principalId, LocalDate effectiveDate) { StringBuffer docDescription = new StringBuffer(); EntityNamePrincipalName principalName = null; if (principalId != null) { principalName = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId); } String personName = (principalName != null && principalName.getDefaultName() != null) ? principalName.getDefaultName().getCompositeName() : StringUtils.EMPTY; String date = TKUtils.formatDate(effectiveDate); docDescription.append(personName + " (" + principalId + ") - " + date); return docDescription.toString(); } /* * aDateTime is the dateTime we would like to display in the fromTimeZone. * The results of the method is the time showing in the toTimeZone considering the time difference between these two time zones */ public static DateTime convertTimeForDifferentTimeZone(DateTime aDateTime, DateTimeZone fromTimeZone, DateTimeZone toTimeZone) { if (fromTimeZone == null || toTimeZone == null || fromTimeZone.equals(toTimeZone)) return aDateTime; // no conversion is needed Long millisOfSysTime = fromTimeZone.getMillisKeepLocal(toTimeZone, aDateTime.getMillis()); DateTime toTime = new DateTime(millisOfSysTime); return toTime; } public static DateTime convertDateTimeToDifferentTimezone(DateTime aDateTime, DateTimeZone fromTimeZone, DateTimeZone toTimeZone) { if (fromTimeZone == null || toTimeZone == null || fromTimeZone.equals(toTimeZone)) return aDateTime; // no conversion is needed Long millisOfSysTime = toTimeZone.getMillisKeepLocal(fromTimeZone, aDateTime.getMillis()); DateTime toTime = new DateTime(millisOfSysTime); return toTime; } public static Assignment getAssignmentWithKey(List<Assignment> assignments, AssignmentDescriptionKey assignmentDescriptionKey) { for (Assignment assignment : assignments) { if (StringUtils.equals(assignment.getGroupKeyCode(), assignmentDescriptionKey.getGroupKeyCode()) && assignment.getJobNumber().compareTo(assignmentDescriptionKey.getJobNumber()) == 0 && assignment.getWorkArea().compareTo(assignmentDescriptionKey.getWorkArea()) == 0 && assignment.getTask().compareTo(assignmentDescriptionKey.getTask()) == 0) { return assignment; } } return null; } }