Java tutorial
/** * * Copyright (c) 2015 Fannie Mae, All rights reserved. * This program and the accompany materials are made available under * the terms of the Fannie Mae Open Source Licensing Project available * at https://github.com/FannieMaeOpenSource/ezPie/wiki/License * * ezPIE is a registered trademark of Fannie Mae * */ package com.fanniemae.ezpie.common; import java.math.BigDecimal; import java.text.MessageFormat; import java.text.ParseException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.UUID; import java.util.regex.Pattern; import org.apache.commons.lang3.time.DateUtils; /** * * @author Rick Monson (richard_monson@fanniemae.com, https://www.linkedin.com/in/rick-monson/) * @since 2015-12-15 * */ public final class StringUtilities { // @formatter:off // Source: http://docs.oracle.com/javase/6/docs/api/java/lang/Double.html#valueOf%28java.lang.String%29 protected static String DOUBLE_REGEX = "[\\x00-\\x20]*[+-]?(NaN|Infinity|((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*"; protected static String BOOLEAN_VALUES = "|true|false|t|f|0|1|yes|no|on|off|y|n|"; protected static String[] SUPPORTED_DATE_FORMATS = new String[] { "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "MM-dd-yyyy HH:mm:ss", "MM/dd/yyyy HH:mm:ss", "dd-MM-yyyy HH:mm:ss", "dd/MM/yyyy HH:mm:ss", "MM-yyyy HH:mm:ss", "MM/yyyy HH:mm:ss", "yyyy-MM-dd'T'HH:mm", "yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "MM-dd-yyyy HH:mm", "MM/dd/yyyy HH:mm", "dd-MM-yyyy HH:mm", "dd/MM/yyyy HH:mm", "MM-yyyy HH:mm", "MM/yyyy HH:mm", "yyyy-MM-dd'T'HH", "yyyy-MM-dd HH", "yyyy/MM/dd HH", "yyyy-MM-dd HH", "yyyy/MM/dd HH", "MM-dd-yyyy HH", "MM/dd/yyyy HH", "dd-MM-yyyy HH", "dd/MM/yyyy HH", "MM-yyyy HH", "MM/yyyy HH", "yyyy-MM-dd", "yyyy/MM/dd", "MM-dd-yyyy", "MM/dd/yyyy", "dd-MM-yyyy", "dd/MM/yyyy", "MM-yyyy", "MM/yyyy", "yyyy-M-dd'T'HH:m:ss", "yyyy-M-dd HH:m:ss", "yyyy/M/dd HH:m:ss", "yyyy-M-dd HH:m:ss", "yyyy/M/dd HH:m:ss", "M-dd-yyyy HH:m:ss", "M/dd/yyyy HH:m:ss", "dd-M-yyyy HH:m:ss", "dd/M/yyyy HH:m:ss", "M-yyyy HH:m:ss", "M/yyyy HH:m:ss", "yyyy-M-dd'T'HH:m", "yyyy-M-dd HH:m", "yyyy/M/dd HH:m", "yyyy-M-dd HH:m", "yyyy/M/dd HH:m", "M-dd-yyyy HH:m", "M/dd/yyyy HH:m", "dd-M-yyyy HH:m", "dd/M/yyyy HH:m", "M-yyyy HH:m", "M/yyyy HH:m", "yyyy-M-dd'T'HH", "yyyy-M-dd HH", "yyyy/M/dd HH", "yyyy-M-dd HH", "yyyy/M/dd HH", "M-dd-yyyy HH", "M/dd/yyyy HH", "dd-M-yyyy HH", "dd/M/yyyy HH", "M-yyyy HH", "M/yyyy HH", "yyyy-M-dd", "yyyy/M/dd", "M-dd-yyyy", "M/dd/yyyy", "dd-M-yyyy", "dd/M/yyyy", "M-yyyy", "M/yyyy", "yyyy-M-d'T'HH:m:ss", "yyyy-M-d HH:m:ss", "yyyy/M/d HH:m:ss", "yyyy-M-d HH:m:ss", "yyyy/M/d HH:m:ss", "M-d-yyyy HH:m:ss", "M/d/yyyy HH:m:ss", "d-M-yyyy HH:m:ss", "d/M/yyyy HH:m:ss", "M-yyyy HH:m:ss", "M/yyyy HH:m:ss", "yyyy-M-d'T'HH:m", "yyyy-M-d HH:m", "yyyy/M/d HH:m", "yyyy-M-d HH:m", "yyyy/M/d HH:m", "M-d-yyyy HH:m", "M/d/yyyy HH:m", "d-M-yyyy HH:m", "d/M/yyyy HH:m", "M-yyyy HH:m", "M/yyyy HH:m", "yyyy-M-d'T'HH", "yyyy-M-d HH", "yyyy/M/d HH", "yyyy-M-d HH", "yyyy/M/d HH", "M-d-yyyy HH", "M/d/yyyy HH", "d-M-yyyy HH", "d/M/yyyy HH", "M-yyyy HH", "M/yyyy HH", "yyyy-M-d", "yyyy/M/d", "M-d-yyyy", "M/d/yyyy", "d-M-yyyy", "d/M/yyyy", "M-yyyy", "M/yyyy", "yyyy-MM-d'T'HH:mm:ss", "yyyy-MM-d HH:mm:ss", "yyyy/MM/d HH:mm:ss", "yyyy-MM-d HH:mm:ss", "yyyy/MM/d HH:mm:ss", "MM-d-yyyy HH:mm:ss", "MM/d/yyyy HH:mm:ss", "d-MM-yyyy HH:mm:ss", "d/MM/yyyy HH:mm:ss", "MM-yyyy HH:mm:ss", "MM/yyyy HH:mm:ss", "yyyy-MM-d'T'HH:mm", "yyyy-MM-d HH:mm", "yyyy/MM/d HH:mm", "yyyy-MM-d HH:mm", "yyyy/MM/d HH:mm", "MM-d-yyyy HH:mm", "MM/d/yyyy HH:mm", "d-MM-yyyy HH:mm", "d/MM/yyyy HH:mm", "MM-yyyy HH:mm", "MM/yyyy HH:mm", "yyyy-MM-d'T'HH", "yyyy-MM-d HH", "yyyy/MM/d HH", "yyyy-MM-d HH", "yyyy/MM/d HH", "MM-d-yyyy HH", "MM/d/yyyy HH", "d-MM-yyyy HH", "d/MM/yyyy HH", "MM-yyyy HH", "MM/yyyy HH", "yyyy-MM-d", "yyyy/MM/d", "MM-d-yyyy", "MM/d/yyyy", "d-MM-yyyy", "d/MM/yyyy", "MM-yyyy", "MM/yyyy", "EEE, d MMM yyyy HH:mm:ss", "d MMM yyyy HH:mm:ss", "d MMM yyyy", "MMM d, yyyy", "MMM dd, yyyy", "yyyy/MM", "yyyy/M", "yyyy-MM", "yyyy-M", "MM/dd/yyyy hh:mm:ss a" }; // @formatter:on private StringUtilities() { } public static boolean isNotNullOrEmpty(String value) { return !isNullOrEmpty(value); } public static boolean isNullOrEmpty(String value) { return (value == null) || value.isEmpty(); } public static boolean isFormattedDate(String value) { // Check for ISO 8601 Date Format (yyyy-MM-ddTHH:mm:ss) if (isNotNullOrEmpty(value) && (value.length() > 14)) { String check = value.substring(4, 5) + value.substring(7, 8) + value.substring(10, 11) + value.substring(13, 14); if ("--T:".equals(check) && isDate(value)) { return true; } } return false; } public static boolean isDate(String value) { try { if (value == null) { return false; } DateUtils.parseDateStrictly(value, SUPPORTED_DATE_FORMATS); return true; } catch (ParseException ex) { return false; } } public static boolean isLong(String value) { if (isNullOrEmpty(value)) return false; value = value.trim(); return (Pattern.matches("^[+-]?\\d+$", value) && (value.length() <= 17)); } public static boolean isInteger(String value) { if (isNullOrEmpty(value)) return false; value = value.trim(); return (Pattern.matches("^[+-]?\\d+$", value) && (value.length() <= 8)); } public static boolean isDouble(String value) { if (isNullOrEmpty(value)) return false; value = value.trim(); if (value.indexOf('.') == -1) return false; return Pattern.matches(DOUBLE_REGEX, value); } public static boolean isBigDecimal(String value) { if (isNullOrEmpty(value)) return false; value = value.trim(); if (value.indexOf('.') == -1) return false; return Pattern.matches(DOUBLE_REGEX, value); } // public static boolean isFormula(String value) { // if (isNullOrEmpty(value)) return false; // char[] aSymbols = ".*/+-()=<>!^#&@$%\\|{}'?".toCharArray(); // for (int i = 0; i < aSymbols.length; i++) { // if (value.indexOf(aSymbols[i]) != -1) { // return true; // } // } // return false; // } public static boolean isBoolean(String value) { return (isNullOrEmpty(value) || (BOOLEAN_VALUES.indexOf("|" + value.trim().toLowerCase() + "|") == -1)) ? false : true; } public static boolean toBoolean(String value) { return toBoolean(value, false); } public static boolean toBoolean(String value, Boolean defaultValue) { if (isNullOrEmpty(value)) return defaultValue; else if ("|true|t|y|1|on|yes|".indexOf("|" + value.trim().toLowerCase() + "|") > -1) return true; else if ("|false|f|n|0|off|no|".indexOf("|" + value.trim().toLowerCase() + "|") > -1) return false; return defaultValue; } public static int toInteger(String value) { return toInteger(value, 0, null); } public static int toInteger(String value, String errorMessage) { return toInteger(value, 0, errorMessage); } public static int toInteger(String value, int defaultValue) { return toInteger(value, defaultValue, null); } public static int toInteger(String value, int defaultValue, String errorMessage) { if (isNullOrEmpty(value)) return defaultValue; try { return Integer.parseInt(value.trim()); } catch (NumberFormatException ex) { if (isNotNullOrEmpty(errorMessage)) { throw new PieException(errorMessage); } return defaultValue; } } public static long toLong(String value) { return toLong(value, 0L); } public static long toLong(String value, long defaultValue) { if (isNullOrEmpty(value)) return defaultValue; try { return Long.parseLong(value.trim()); } catch (NumberFormatException ex) { return defaultValue; } } public static double toDouble(String value) { return toDouble(value, 0.0); } public static double toDouble(String value, double defaultValue) { if (isNullOrEmpty(value)) return defaultValue; try { return Double.parseDouble(value.trim()); } catch (NumberFormatException ex) { return defaultValue; } } public static BigDecimal toBigDecimal(String value) { return toBigDecimal(value, new BigDecimal("0.0")); } public static BigDecimal toBigDecimal(String value, BigDecimal defaultValue) { if (isNullOrEmpty(value)) return defaultValue; try { return new BigDecimal(value.trim()); } catch (NumberFormatException ex) { return defaultValue; } } public static Date toDate(String value) { return toDate(value, null); } public static Date toDate(String value, Date defaultValue) { try { if (value == null) { return defaultValue; } return DateUtils.parseDateStrictly(value, SUPPORTED_DATE_FORMATS); } catch (ParseException ex) { return defaultValue; } } public static LocalDateTime toDateTime(String s, LocalDateTime defaultValue) { if (StringUtilities.isNullOrEmpty(s)) return defaultValue; try { DateTimeFormatter fmt = DateTimeFormatter.ISO_DATE_TIME; return LocalDateTime.parse(s, fmt); } catch (Exception ex) { ExceptionUtilities.goSilent(ex); return defaultValue; } } public static Object toObject(String typeName, String value) { if ((value == null) || value.isEmpty()) { return ""; } switch (typeName) { case "Boolean": return Boolean.parseBoolean(value); case "Byte": case "SByte": return Byte.parseByte(value); case "Byte[]": return value.toCharArray(); case "Char": return value.charAt(0); case "Char[]": return value.toCharArray(); case "DateTime": Date dtValue = new Date(Long.parseLong(value)); if (dtValue == new Date(Long.MIN_VALUE)) { return null; } return dtValue; case "Decimal": case "Double": case "Single": return Double.parseDouble(value); case "Float": return Float.parseFloat(value); case "UUID": return UUID.fromString(value); case "Int": case "Integer": case "Int16": case "Int32": case "UInt16": return Integer.parseInt(value); case "Int64": case "Long": case "UInt32": case "UInt64": return Long.parseLong(value); case "NCLOB": return "NCLOB"; case "Short": return Short.parseShort(value); case "String": return value; case "TimeSpan": return value; default: return null; } } public static String wrapValue(String value) { if ((value == null) || (value.indexOf(' ') == -1)) return value; if ((value.startsWith("\"") && value.endsWith("\""))) return value; return String.format("\"%s\"", value); } public static String getDataType(String value, String previousType) { if (isNullOrEmpty(value)) { return previousType; } else if (isNullOrEmpty(previousType)) { if (isBoolean(value)) { return "BooleanData"; } else if (isDate(value)) { return "DateData"; } else if (isInteger(value)) { return "IntegerData"; } else if (isLong(value)) { return "LongData"; } else if (isDouble(value)) { return "DoubleData"; } else if (isBigDecimal(value)) { return "BigDecimal"; } else { return "StringData"; } } else if ("StringData".equals(previousType)) { return previousType; } else if ("BooleanData".equals(previousType)) { return isBoolean(value) ? "BooleanData" : "StringData"; } else if ("DateData".equals(previousType)) { return isDate(value) ? previousType : "StringData"; } else if ("IntegerData".equals(previousType) && isInteger(value)) { return previousType; } else if (("IntegerData".equals(previousType) || "LongData".equals(previousType)) && isLong(value)) { return "LongData"; } else if (("|IntegerData|LongData|DoubleData|".indexOf("|" + previousType + "|") > -1) && isDouble(value)) { return "DoubleData"; } else if ("|IntegerData|LongData|DoubleData|BigDecimalData".indexOf("|" + previousType + "|") > -1) { return isBigDecimal(value) ? "BigDecimalData" : "StringData"; } else if (isNotNullOrEmpty(previousType)) { return "StringData"; } else { throw new RuntimeException("Unable to detect delimited file schema format."); } } public static String[] split(String value) { return split(value, ","); } public static String[] split(String value, String regex) { if (isNullOrEmpty(value)) return new String[0]; String[] values = value.split(regex); int length = values.length; for (int i = 0; i < length; i++) { values[i] = values[i].trim(); } return values; } public static int periodToMinutes(String value) { if (StringUtilities.isInteger(value)) { value += 'm'; } int seconds = periodToSeconds(value); if (seconds < 60) { return -1; } return (seconds / 60); } public static int periodToSeconds(String value) { if (StringUtilities.isNullOrEmpty(value)) return -1; char cUnits = 's'; int iStart = 0; int iSeconds = 0; int iPosition = 0; int iCurrentValue = 0; value = value.toLowerCase(); String[] aNumbers = value.split("y|w|d|h|m|s"); for (int i = 0; i < aNumbers.length; i++) { if (StringUtilities.isNullOrEmpty(aNumbers[i])) continue; iPosition = value.indexOf(aNumbers[i], iStart) + aNumbers[i].length(); iStart = iPosition + 1; cUnits = (iPosition < value.length()) ? value.charAt(iPosition) : 's'; iCurrentValue = StringUtilities.toInteger(aNumbers[i], 0, null); switch (cUnits) { case 'y': iSeconds += iCurrentValue * 31536000; break; case 'w': iSeconds += iCurrentValue * 604800; break; case 'd': iSeconds += iCurrentValue * 86400; break; case 'h': iSeconds += iCurrentValue * 3600; break; case 'm': iSeconds += iCurrentValue * 60; break; case 's': iSeconds += iCurrentValue; break; } } return (iSeconds < 1) ? -1 : iSeconds; } public static String formatAsNumber(double value) { BigDecimal valueOf = BigDecimal.valueOf(value); BigDecimal integerPart = BigDecimal.valueOf(valueOf.longValue()); BigDecimal fractional = valueOf.subtract(integerPart); String fraction = fractional.toPlainString(); int indexOfDot = fraction.indexOf('.') + 1; String sign = fraction.startsWith("-") ? "-" : ""; fraction = fraction.length() > indexOfDot ? fraction.substring(indexOfDot) : fraction; if (fraction.equals("0")) { return MessageFormat.format("{0}{1}", sign, integerPart.toPlainString(), fraction); } else { return MessageFormat.format("{0}{1}.{2}", sign, integerPart.toPlainString(), fraction); } } }