You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StringUtil.java 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package com.healthmarketscience.jackcess.util;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Modifier;
  4. import java.nio.CharBuffer;
  5. import java.util.Arrays;
  6. import java.util.Comparator;
  7. import java.util.concurrent.atomic.AtomicBoolean;
  8. import java.util.stream.IntStream;
  9. /**
  10. * <p>
  11. * Static utility methods for null-safe {@link String} operations.
  12. * </p>
  13. *
  14. * The class prefers interface {@link CharSequence} for inputs over
  15. * {@code String} whenever possible, so that all implementations (e.g.
  16. * {@link StringBuffer}, {@link StringBuilder}, {@link CharBuffer}) can benefit.
  17. *
  18. * @author Markus Spann
  19. */
  20. public final class StringUtil
  21. {
  22. private StringUtil() {
  23. }
  24. /**
  25. * Gets the given char sequence's length or {@code 0} if it is {@code null}.
  26. *
  27. * @param cs string
  28. * @return length of string
  29. */
  30. public static int length(CharSequence cs)
  31. {
  32. return cs == null ? 0 : cs.length();
  33. }
  34. /**
  35. * Checks if the given char sequence is either null or empty.
  36. *
  37. * @param cs char sequence to test
  38. * @return true if char sequence is empty or null, false otherwise
  39. */
  40. public static boolean isEmpty(CharSequence cs)
  41. {
  42. return length(cs) == 0;
  43. }
  44. /**
  45. * Returns {@code true} if the given char sequence is {@code null} or all blank space,
  46. * {@code false} otherwise.
  47. */
  48. public static boolean isBlank(CharSequence cs)
  49. {
  50. int len = length(cs);
  51. return len == 0 || IntStream.range(0, len).allMatch(i -> Character.isWhitespace(cs.charAt(i)));
  52. }
  53. /**
  54. * Returns the given char sequence trimmed or {@code null} if the string is {@code null} or empty.
  55. */
  56. public static String trimToNull(CharSequence cs)
  57. {
  58. String str = cs == null ? null : cs.toString().trim();
  59. return isEmpty(str) ? null : str;
  60. }
  61. /**
  62. * Capitalizes a string changing its first character to title case as per
  63. * {@link Character#toTitleCase(int)}.
  64. */
  65. public static String capitalize(String str)
  66. {
  67. if (isEmpty(str)) {
  68. return str;
  69. }
  70. int cp = str.codePointAt(0);
  71. int newCp = Character.toTitleCase(cp);
  72. return cp == newCp ? str : new String(Character.toString((char) newCp)) + str.substring(1);
  73. }
  74. public static String replace(String text, CharSequence searchString, CharSequence replacement)
  75. {
  76. return isEmpty(text) || isEmpty(searchString) ? text : text.replace(searchString, replacement);
  77. }
  78. /**
  79. * Removes all occurrences of character sequence {@code remove} from string {@code cs}.
  80. *
  81. * @param cs the character sequence to remove from
  82. * @param remove the character sequence to remove
  83. * @return modified input
  84. */
  85. public static String remove(CharSequence cs, CharSequence remove)
  86. {
  87. if (cs == null) {
  88. return null;
  89. }
  90. int len = cs.length();
  91. if (len == 0) {
  92. return "";
  93. } else if (isEmpty(remove) || remove.length() > len) {
  94. return cs.toString();
  95. }
  96. return cs.toString().replace(remove, "");
  97. }
  98. /**
  99. * Generates a string representation of {@code obj} using reflection on its
  100. * non-static declared fields.
  101. *
  102. * @param obj object to generate string from
  103. * @param longClassName use full class name if {@code true} or simple name if
  104. * {@code false}
  105. * @param hashCode include the object's hash code if {@code true}
  106. * @return string representation
  107. */
  108. public static String reflectionToString(Object obj, boolean longClassName, boolean hashCode)
  109. {
  110. if (obj == null) {
  111. return "null";
  112. }
  113. StringBuilder sb = new StringBuilder(longClassName ? obj.getClass().getName() : obj.getClass().getSimpleName());
  114. if (hashCode) {
  115. sb.append('@').append(Integer.toHexString(System.identityHashCode(obj)));
  116. }
  117. sb.append('[');
  118. AtomicBoolean firstField = new AtomicBoolean(true);
  119. Arrays.stream(obj.getClass().getDeclaredFields())
  120. .filter(f -> !Modifier.isStatic(f.getModifiers()))
  121. .sorted(Comparator.comparing(Field::getName))
  122. .forEach(f -> {
  123. f.setAccessible(true);
  124. if (!firstField.compareAndSet(true, false)) {
  125. sb.append(',');
  126. }
  127. sb.append(f.getName()).append('=');
  128. try {
  129. Object val = f.get(obj);
  130. sb.append(val == null ? "<null>" : val);
  131. } catch (Exception _ex) {
  132. sb.append('<').append(_ex).append('>');
  133. }
  134. });
  135. return sb.append(']').toString();
  136. }
  137. /**
  138. * Generates a string representation of {@code obj} using reflection on its
  139. * non-static declared fields using the object's full class name and including
  140. * the object's hash code.<br>
  141. *
  142. * @param obj object to generate string from
  143. * @return string representation
  144. */
  145. public static String reflectionToString(Object obj) {
  146. return reflectionToString(obj, true, true);
  147. }
  148. }