Rev 37070 | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.spice.profitmandi.common.util;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.spice.profitmandi.common.enumuration.DateTimePattern;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import javax.mail.internet.InternetAddress;import java.text.Normalizer;import java.time.*;import java.time.format.DateTimeFormatter;import java.time.format.DateTimeParseException;import java.util.ArrayList;import java.util.List;import java.util.Locale;import java.util.regex.Matcher;import java.util.regex.Pattern;public class StringUtils {private static ObjectMapper objectMapper = new ObjectMapper();private static final Logger LOGGER = LogManager.getLogger(StringUtils.class);private static final String DATE_PATTERN = "dd/MM/yyyy";private static final String GADGET_COP_DATE_PATTERN = "MM/dd/yyyy";private static final String DATE_TIME_PATTERN = "dd/MM/yyyy HH:mm:ss";private static final String DATE_PATTERN_HYPHENATED = "dd-MM-yyyy";private static final String DATE_TIME_ABBR = "dd/MM/yyyy hh:mma";private static final DateTimeFormatter SHORT_MONTH_DATE_FORMATTER = DateTimeFormatter.ofPattern("d-MMM-yyyy");private static final DateTimeFormatter SHORT_MONTH_DATE_YEAR_FORMATTER = DateTimeFormatter.ofPattern("dd-MMM-yy");private StringUtils(){}private static final Pattern WHITESPACE_RUN = Pattern.compile("[\\s\\u00A0\\u1680\\u2000-\\u200B\\u202F\\u205F\\u3000\\uFEFF]+");/*** Normalizes whitespace: replaces every run of whitespace-like characters* (spaces, tabs, CR/LF, non-breaking space , other Unicode spaces and* zero-width characters) with a single regular space, then trims. Non-whitespace* symbols (e.g. the degree sign) are preserved. Null-safe.*/public static String normalizeWhitespace(String value) {if (value == null) {return null;}return WHITESPACE_RUN.matcher(value).replaceAll(" ").trim();}public static final LocalDate fromShortMonthDateYear(String dateString) throws DateTimeParseException {dateString = dateString.toLowerCase();dateString = StringUtils.capitalizeFirstChar(dateString);return LocalDate.parse(dateString, SHORT_MONTH_DATE_YEAR_FORMATTER);}public static final LocalDate fromShortMonthDate(String dateString) throws DateTimeParseException {dateString = StringUtils.capitalizeFirstChar(dateString);return LocalDate.parse(dateString, SHORT_MONTH_DATE_FORMATTER);}public static final LocalDate toDate(String dateString)throws DateTimeParseException{LOGGER.info("Converting dateString [{}] with pattern[{}]", dateString, DATE_PATTERN);DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);return LocalDate.parse(dateString, dateTimeFormatter);}public static final LocalDate toDate(String dateString, String pattern)throws DateTimeParseException{LOGGER.info("Converting dateString [{}] with pattern[{}]", dateString, pattern);DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);return LocalDate.parse(dateString, dateTimeFormatter);}public static final String toGadgetCopDateString(LocalDate ldt) {DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(GADGET_COP_DATE_PATTERN);return dateTimeFormatter.format(ldt);}public static final LocalDate fromHypendatedDate(String dateString)throws DateTimeParseException{LOGGER.info("Converting dateString [{}] with pattern[{}]", dateString, DATE_PATTERN_HYPHENATED);DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN_HYPHENATED);return LocalDate.parse(dateString, dateTimeFormatter);}public static final LocalTime toTime(String timeString) throws DateTimeParseException{return LocalTime.parse(timeString);}public static final LocalTime secondsToTime(double totalSeconds) throws DateTimeParseException{int totalSecs = (int) Math.round(totalSeconds);int hours = totalSecs / 3600;int minutes = (totalSecs % 3600) / 60;int seconds = totalSecs % 60;String timeString = String.format("%02d:%02d:%02d", hours, minutes, seconds);return LocalTime.parse(timeString);}public static final LocalTime timeDifference(LocalTime startTime, LocalTime endTime) throws DateTimeParseException{Duration duration = Duration.between(startTime, endTime);if (duration.isNegative()) {duration = duration.plusHours(24); // handle case when now is past midnight}long hours = duration.toHours();long minutes = duration.toMinutes() % 60;long seconds = duration.getSeconds() % 60;return LocalTime.of((int) hours % 24, (int) minutes, (int) seconds);}public static final LocalDateTime toDateTime(long epocTime){return Instant.ofEpochMilli(epocTime).atZone(ZoneId.systemDefault()).toLocalDateTime();}public static final String toString(LocalDate localDate){DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_PATTERN);String formattedDateTime = localDate.format(formatter);return formattedDateTime;}public static final String toHyphenatedString(LocalDate localDate){DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_PATTERN_HYPHENATED);String formattedDateTime = localDate.format(formatter);return formattedDateTime;}public static final String toString(LocalDateTime localDateTime){if(localDateTime == null){return null;}DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-YYYY HH:mm:ss");return localDateTime.format(formatter);}public static final LocalDateTime toDateTime(String dateTimeString) throws DateTimeParseException{if(dateTimeString == null || dateTimeString.equals("0") || dateTimeString.isEmpty()){return null;}DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);return LocalDateTime.parse(dateTimeString, dateTimeFormatter);}public static final String toLocalDateTime(String dateTimeString) throws DateTimeParseException{if(dateTimeString == null || dateTimeString.equals("0") || dateTimeString.isEmpty()){return null;}LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, DateTimeFormatter.ISO_LOCAL_DATE_TIME);DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(DATE_TIME_ABBR);return dateTime.format(outputFormatter);}public static final LocalDateTime toDateTime(String dateTimeString, DateTimePattern dateTimePattern) throws DateTimeParseException{if(dateTimeString == null || dateTimeString.equals("0") || dateTimeString.isEmpty()){return null;}DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateTimePattern.getValue());return LocalDateTime.parse(dateTimeString, formatter);}public static boolean isValidMobile(String mobile){try{Long.valueOf(mobile);}catch(Exception e){return false;}if (mobile.startsWith("0")){return false;}if (mobile.length()!=10){return false;}return true;}public static boolean isValidEmailAddress(String email) {boolean result = true;try {InternetAddress emailAddr = new InternetAddress(email);emailAddr.validate();} catch (Exception ex) {result = false;}return result;}/** Characters of a GSTIN, in the order the checksum weights them. */private static final String GSTIN_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";/*** 2-digit state code, 10-char PAN (5 letters, 4 digits, 1 letter), entity number,* the literal Z, then the checksum character.*/private static final java.util.regex.Pattern GSTIN_PATTERN =java.util.regex.Pattern.compile("^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$");/** State codes issued by GSTN: 01-38, plus 97 (other territory) and 99 (centre). */private static final java.util.regex.Pattern GSTIN_STATE_CODE =java.util.regex.Pattern.compile("^(0[1-9]|[12][0-9]|3[0-8]|97|99)$");/*** Whether a GSTIN is well formed: shape, a real state code, and the mod-36 checksum in the* 15th character. A blank is still allowed - the field is optional for stores that have no* registration - so callers that need one present must check for that themselves.* <p>* It used to accept any 15-character string, which let a pincode ({@code 110095}, rejected* only for being 6 characters) and outright junk ({@code Hdjiekwbdbsjskz}) reach* fofo_store.gst_number, where billing reads it. NIC then rejects the invoice and the goods* cannot ship. The checksum is worth having on top of the shape: of 1,570 well-formed* partner GSTINs on record exactly one fails it, so it costs nothing and catches the* transposed or O-for-0 typo that the pattern alone cannot see.*/public static boolean isValidGstNumber(String gstNumber) {if(gstNumber == null || gstNumber.trim().isEmpty()) {return true;}String gstin = normalizeGstNumber(gstNumber);if(!GSTIN_PATTERN.matcher(gstin).matches()) {return false;}if(!GSTIN_STATE_CODE.matcher(gstin.substring(0, 2)).matches()) {return false;}return gstin.charAt(14) == gstinChecksum(gstin);}/** Trimmed and upper-cased, so the same registration is never stored two ways. */public static String normalizeGstNumber(String gstNumber) {return gstNumber == null ? null : gstNumber.trim().toUpperCase();}/*** GSTN's mod-36 check character over the first 14 characters: each is weighted 1, 2, 1, 2 ...* and the two digits of each product are added separately before the total is complemented.*/private static char gstinChecksum(String gstin) {int total = 0;for(int i = 0; i < 14; i++) {int product = GSTIN_ALPHABET.indexOf(gstin.charAt(i)) * (i % 2 == 0 ? 1 : 2);total += product / 36 + product % 36;}return GSTIN_ALPHABET.charAt((36 - total % 36) % 36);}public static List<String> getDuplicateElements(List<String> elements){List<String> duplicates = new ArrayList<>();for(int i = 0; i < elements.size(); i++){for(int j = i + 1; j < elements.size(); j++){if(elements.get(i).equals(elements.get(j))){duplicates.add(elements.get(i));}}}return duplicates;}public static String toString(Object object) throws Exception{try {return objectMapper.writeValueAsString(object);} catch (JsonProcessingException e) {LOGGER.error("Error occured while converting object to json", e);throw e;}}public static boolean isValidPinCode(String pinCode){if(pinCode == null || pinCode.isEmpty()){return false;}if(pinCode.length() != 6){return false;}if(pinCode.startsWith("00") || pinCode.startsWith("01") || pinCode.startsWith("10")){return false;}return true;}public static String generatePolicyNumber(String prefix, int sequence){String policyNumber = String.format(prefix + "%06d", sequence);LOGGER.info("Generated Policy Number [{}]", policyNumber);return policyNumber;}public static String generateFofoStoreSequence(String prefix, int sequence){String fofoStoreSequenceNumber = String.format(prefix + "%03d", sequence);LOGGER.info("Generated Fofo Store Sequence Number [{}]", fofoStoreSequenceNumber);return fofoStoreSequenceNumber;}public static String generateRechageRequestId(String prefix, int sequence){String oxigenRechargeRequestId = String.format(prefix + "%06d", sequence);LOGGER.info("Generated Recharge Request Id [{}]", oxigenRechargeRequestId);return oxigenRechargeRequestId;}public static String generateDeliveryNoteId(String prefix, int sequence){String deliveryNoteId = String.format(prefix + "%06d", sequence);LOGGER.info("Generated Delivery Note Id [{}]", deliveryNoteId);return deliveryNoteId;}public static String toOxigenRechargeRequestDate(LocalDateTime now){StringBuilder oxigenRechargeRequestDate = new StringBuilder();oxigenRechargeRequestDate.append(now.getYear());oxigenRechargeRequestDate.append(now.getMonthValue());oxigenRechargeRequestDate.append(now.getDayOfMonth());oxigenRechargeRequestDate.append(now.getHour());oxigenRechargeRequestDate.append(now.getMinute());oxigenRechargeRequestDate.append(now.getSecond());return oxigenRechargeRequestDate.toString();}public static LocalDateTime fromOxigenRechargeRequestDate(String oxigenRechargeRequestDate){int year = Integer.parseInt(oxigenRechargeRequestDate.substring(0, 3));int month = Integer.parseInt(oxigenRechargeRequestDate.substring(4, 5));int dayOfMonth = Integer.parseInt(oxigenRechargeRequestDate.substring(6, 7));int hour = Integer.parseInt(oxigenRechargeRequestDate.substring(8, 9));int minute = Integer.parseInt(oxigenRechargeRequestDate.substring(10, 11));int second = Integer.parseInt(oxigenRechargeRequestDate.substring(12, 13));return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second);}public static String capitalizeFirstChar(String input) {if (input == null || input.isEmpty()) {return input; // Return the input if it's null or empty}// Define the regular expression to match the first alphabetic characterPattern pattern = Pattern.compile("([a-zA-Z])");Matcher matcher = pattern.matcher(input);// If the first character matches, capitalize itif (matcher.find()) {return matcher.replaceFirst(matcher.group(1).toUpperCase());}return input; // If no match is found, return the original string}public static String formatDistance(double distanceInMeters) {if (distanceInMeters <= 950) {int roundedMeters = ((int) Math.ceil(distanceInMeters / 100.0)) * 100;double distanceKm = roundedMeters / 1000.0;return String.format("%.2f", distanceKm);} else {return String.format("%.2f", distanceInMeters / 1000.0);}}public static String toSlug(String input) {if (input == null) return "";String normalized = Normalizer.normalize(input, Normalizer.Form.NFD).replaceAll("\\p{M}", "");String lowerCase = normalized.toLowerCase(Locale.ENGLISH);String slug = lowerCase.replaceAll("[^a-z0-9]+", "-");slug = slug.replaceAll("^-+|-+$", "");return slug;}}