Merge branch 'deeseja-master'
This commit is contained in:
Shekhar Gulati
2017-05-20 23:27:22 +05:30
3 changed files with 122 additions and 91 deletions
+9
View File
@@ -631,6 +631,15 @@ isBlank("test")
// result => false) // result => false)
``` ```
## underscored
`underscored` function converts a camel or dashed string into an underscored one
```java
underscored("MozTransform")
// result => "moz_transform")
```
## Inspiration ## Inspiration
This library is inspired by [dleitee/strman](https://github.com/dleitee/strman). This library is inspired by [dleitee/strman](https://github.com/dleitee/strman).
+71 -73
View File
@@ -1,4 +1,3 @@
/* /*
* *
* * The MIT License * * The MIT License
@@ -35,9 +34,7 @@ import java.util.regex.Pattern;
import java.util.stream.Stream; import java.util.stream.Stream;
import static java.util.function.Function.identity; import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.*;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
/** /**
* A String manipulation library without any dependencies * A String manipulation library without any dependencies
@@ -119,7 +116,8 @@ public abstract class Strman {
validate(end, NULL_STRING_PREDICATE, () -> "'end' should be not null."); validate(end, NULL_STRING_PREDICATE, () -> "'end' should be not null.");
String[] parts = value.split(end); String[] parts = value.split(end);
return Arrays.stream(parts).map(subPart -> subPart.substring(subPart.indexOf(start) + start.length())).toArray(String[]::new); return Arrays.stream(parts).map(subPart -> subPart.substring(subPart.indexOf(start) + start.length()))
.toArray(String[]::new);
} }
/** /**
@@ -133,7 +131,6 @@ public abstract class Strman {
return value.split(""); return value.split("");
} }
/** /**
* Replace consecutive whitespace characters with a single space. * Replace consecutive whitespace characters with a single space.
* *
@@ -145,7 +142,6 @@ public abstract class Strman {
return value.trim().replaceAll("\\s\\s+", " "); return value.trim().replaceAll("\\s\\s+", " ");
} }
/** /**
* Verifies that the needle is contained in the value. The search is case insensitive * Verifies that the needle is contained in the value. The search is case insensitive
* *
@@ -242,9 +238,11 @@ public abstract class Strman {
* @param allowOverlapping boolean to take into account overlapping * @param allowOverlapping boolean to take into account overlapping
* @return count of times substring exists * @return count of times substring exists
*/ */
public static long countSubstr(final String value, final String subStr, final boolean caseSensitive, boolean allowOverlapping) { public static long countSubstr(final String value, final String subStr, final boolean caseSensitive,
boolean allowOverlapping) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return countSubstr(caseSensitive ? value : value.toLowerCase(), caseSensitive ? subStr : subStr.toLowerCase(), allowOverlapping, 0L); return countSubstr(caseSensitive ? value : value.toLowerCase(), caseSensitive ? subStr : subStr.toLowerCase(),
allowOverlapping, 0L);
} }
/** /**
@@ -281,7 +279,8 @@ public abstract class Strman {
* @param caseSensitive true or false * @param caseSensitive true or false
* @return true or false * @return true or false
*/ */
public static boolean endsWith(final String value, final String search, final int position, final boolean caseSensitive) { public static boolean endsWith(final String value, final String search, final int position,
final boolean caseSensitive) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
int remainingLength = position - search.length(); int remainingLength = position - search.length();
if (caseSensitive) { if (caseSensitive) {
@@ -640,7 +639,8 @@ public abstract class Strman {
* @param caseSensitive whether search should be case sensitive * @param caseSensitive whether search should be case sensitive
* @return Return position of the last occurrence of 'needle'. * @return Return position of the last occurrence of 'needle'.
*/ */
public static int lastIndexOf(final String value, final String needle, final int offset, final boolean caseSensitive) { public static int lastIndexOf(final String value, final String needle, final int offset,
final boolean caseSensitive) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
validate(needle, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(needle, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
if (caseSensitive) { if (caseSensitive) {
@@ -775,7 +775,8 @@ public abstract class Strman {
public static String removeRight(final String value, final String suffix, final boolean caseSensitive) { public static String removeRight(final String value, final String suffix, final boolean caseSensitive) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
validate(suffix, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(suffix, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return endsWith(value, suffix, caseSensitive) ? value.substring(0, value.toLowerCase().lastIndexOf(suffix.toLowerCase())) : value; return endsWith(value, suffix, caseSensitive) ? value
.substring(0, value.toLowerCase().lastIndexOf(suffix.toLowerCase())) : value;
} }
/** /**
@@ -810,13 +811,15 @@ public abstract class Strman {
* @param caseSensitive whether search should be case sensitive or not * @param caseSensitive whether search should be case sensitive or not
* @return String replaced with 'newvalue'. * @return String replaced with 'newvalue'.
*/ */
public static String replace(final String value, final String search, final String newValue, final boolean caseSensitive) { public static String replace(final String value, final String search, final String newValue,
final boolean caseSensitive) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
validate(search, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(search, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
if (caseSensitive) { if (caseSensitive) {
return value.replace(search, newValue); return value.replace(search, newValue);
} }
return Pattern.compile(search, Pattern.CASE_INSENSITIVE).matcher(value).replaceAll(Matcher.quoteReplacement(newValue)); return Pattern.compile(search, Pattern.CASE_INSENSITIVE).matcher(value)
.replaceAll(Matcher.quoteReplacement(newValue));
} }
/** /**
@@ -950,11 +953,8 @@ public abstract class Strman {
*/ */
public static String htmlEncode(final String html) { public static String htmlEncode(final String html) {
validate(html, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(html, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return html return html.chars().mapToObj(c -> "\\u" + String.format("%04x", c).toUpperCase())
.chars() .map(HtmlEntities.encodedEntities::get).collect(joining());
.mapToObj(c -> "\\u" + String.format("%04x", c).toUpperCase())
.map(HtmlEntities.encodedEntities::get)
.collect(joining());
} }
/** /**
@@ -1019,7 +1019,6 @@ public abstract class Strman {
return result; return result;
} }
/** /**
* Surrounds a 'value' with the given 'prefix' and 'suffix'. * Surrounds a 'value' with the given 'prefix' and 'suffix'.
* *
@@ -1055,10 +1054,7 @@ public abstract class Strman {
public static String toStudlyCase(final String value) { public static String toStudlyCase(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
String[] words = collapseWhitespace(value.trim()).split("\\s*(_|-|\\s)\\s*"); String[] words = collapseWhitespace(value.trim()).split("\\s*(_|-|\\s)\\s*");
return Arrays.stream(words) return Arrays.stream(words).filter(w -> !w.trim().isEmpty()).map(Strman::upperFirst).collect(joining());
.filter(w -> !w.trim().isEmpty())
.map(Strman::upperFirst)
.collect(joining());
} }
/** /**
@@ -1106,8 +1102,7 @@ public abstract class Strman {
public static String decode(final String value, final int digits, final int radix) { public static String decode(final String value, final int digits, final int radix) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return Arrays return Arrays.stream(value.split("(?<=\\G.{" + digits + "})"))
.stream(value.split("(?<=\\G.{" + digits + "})"))
.map(data -> String.valueOf(Character.toChars(Integer.parseInt(data, radix)))) .map(data -> String.valueOf(Character.toChars(Integer.parseInt(data, radix))))
.collect(joining()); .collect(joining());
} }
@@ -1117,7 +1112,6 @@ public abstract class Strman {
return value.chars().mapToObj(ch -> leftPad(Integer.toString(ch, radix), "0", digits)).collect(joining()); return value.chars().mapToObj(ch -> leftPad(Integer.toString(ch, radix), "0", digits)).collect(joining());
} }
/** /**
* Join concatenates all the elements of the strings array into a single String. The separator string is placed between elements in the resulting string. * Join concatenates all the elements of the strings array into a single String. The separator string is placed between elements in the resulting string.
* *
@@ -1152,11 +1146,7 @@ public abstract class Strman {
if (input.length() == 0) { if (input.length() == 0) {
return ""; return "";
} }
return head(input) return head(input).map(String::toUpperCase).map(h -> tail(input).map(t -> h + t.toLowerCase()).orElse(h)).get();
.map(String::toUpperCase)
.map(h ->
tail(input).map(t -> h + t.toLowerCase()).orElse(h))
.get();
} }
/** /**
@@ -1174,11 +1164,7 @@ public abstract class Strman {
return ""; return "";
} }
return head(input) return head(input).map(String::toLowerCase).map(h -> tail(input).map(t -> h + t).orElse(h)).get();
.map(String::toLowerCase)
.map(h ->
tail(input).map(t -> h + t).orElse(h))
.get();
} }
/** /**
@@ -1223,10 +1209,7 @@ public abstract class Strman {
if (input == null) { if (input == null) {
throw new IllegalArgumentException("input can't be null"); throw new IllegalArgumentException("input can't be null");
} }
return head(input) return head(input).map(String::toUpperCase).map(h -> tail(input).map(t -> h + t).orElse(h)).get();
.map(String::toUpperCase)
.map(h -> tail(input).map(t -> h + t).orElse(h))
.get();
} }
/** /**
@@ -1236,27 +1219,21 @@ public abstract class Strman {
* @return Returns the trimmed string. * @return Returns the trimmed string.
*/ */
public static Optional<String> trimStart(final String input) { public static Optional<String> trimStart(final String input) {
return Optional.ofNullable(input) return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(Strman::leftTrim);
.filter(v -> !v.isEmpty())
.map(Strman::leftTrim);
} }
/** /**
* Removes leading characters from string. * Removes leading characters from string.
* *
* @param input The string to trim. * @param input The string to trim.
* @param chars The characters to trim. * @param chars The characters to trim.
*
* @return Returns the trimmed string. * @return Returns the trimmed string.
*/ */
public static Optional<String> trimStart(final String input, String... chars) { public static Optional<String> trimStart(final String input, String... chars) {
return Optional.ofNullable(input) return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(v -> {
.filter(v -> !v.isEmpty()) String pattern = String.format("^[%s]+", join(chars, "\\"));
.map(v -> { return v.replaceAll(pattern, "");
String pattern = String.format("^[%s]+", join(chars, "\\")); });
return v.replaceAll(pattern, "");
});
} }
/** /**
@@ -1266,30 +1243,23 @@ public abstract class Strman {
* @return Returns the trimmed string. * @return Returns the trimmed string.
*/ */
public static Optional<String> trimEnd(final String input) { public static Optional<String> trimEnd(final String input) {
return Optional.ofNullable(input) return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(Strman::rightTrim);
.filter(v -> !v.isEmpty())
.map(Strman::rightTrim);
} }
/** /**
* Removes trailing characters from string. * Removes trailing characters from string.
* *
* @param input The string to trim. * @param input The string to trim.
* @param chars The characters to trim. * @param chars The characters to trim.
*
* @return Returns the trimmed string. * @return Returns the trimmed string.
*/ */
public static Optional<String> trimEnd(final String input, String... chars) { public static Optional<String> trimEnd(final String input, String... chars) {
return Optional.ofNullable(input) return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(v -> {
.filter(v -> !v.isEmpty()) String pattern = String.format("[%s]+$", join(chars, "\\"));
.map(v -> { return v.replaceAll(pattern, "");
String pattern = String.format("[%s]+$", join(chars, "\\")); });
return v.replaceAll(pattern, "");
});
} }
/** /**
* Counts the number of occurrences of each character in the string * Counts the number of occurrences of each character in the string
* *
@@ -1301,20 +1271,48 @@ public abstract class Strman {
return Collections.emptyMap(); return Collections.emptyMap();
} }
return input.chars() return input.chars().mapToObj(c -> (char) c).collect(groupingBy(identity(), counting()));
.mapToObj(c -> (char) c)
.collect(groupingBy(identity(), counting()));
} }
/** /**
* Checks if string is empty. This is a null safe check and will return true when string is null. * Checks if string is empty. This is a null safe check and will return true when string is null.
* *
* @param input The input string * @param input The input string
* @return true if string is null or empty * @return true if input string is null or empty
*/ */
public static boolean isBlank(String input) { public static boolean isBlank(String input) {
return input == null || input.isEmpty(); return input == null || input.isEmpty();
} }
/**
* Changes passed in string to all lower case and adds underscore between words.
*
* @param input The input string
* @return the input string in all lower case with underscores between words
*/
public static String underscored(final String input) {
if (input == null) {
return null;
}
StringBuilder builder = new StringBuilder();
char[] chars = collapseWhitespace(input).toCharArray();
for (int index = 0; index < chars.length; index++) {
char ch = chars[index];
if (index > 0) {
if (ch == '-' || Character.isWhitespace(ch)) {
builder.append("_");
} else if (Character.isUpperCase(ch)) {
builder.append("_");
builder.append(ch);
} else {
builder.append(ch);
}
} else {
builder.append(ch);
}
}
return builder.toString().toLowerCase();
}
private static void validate(String value, Predicate<String> predicate, final Supplier<String> supplier) { private static void validate(String value, Predicate<String> predicate, final Supplier<String> supplier) {
if (predicate.test(value)) { if (predicate.test(value)) {
@@ -1335,6 +1333,6 @@ public abstract class Strman {
} }
return countSubstr(value.substring(offset), subStr, allowOverlapping, ++count); return countSubstr(value.substring(offset), subStr, allowOverlapping, ++count);
} }
} }
+42 -18
View File
@@ -37,6 +37,7 @@ import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining;
import static org.hamcrest.collection.IsArrayWithSize.emptyArray; import static org.hamcrest.collection.IsArrayWithSize.emptyArray;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static strman.Strman.*; import static strman.Strman.*;
import static strman.Strman.endsWith;
public class StrmanTest { public class StrmanTest {
@@ -990,34 +991,34 @@ public class StrmanTest {
@Test @Test
public void charsCount_shouldReturnEmptyWhenInputStringIsNull(){ public void charsCount_shouldReturnEmptyWhenInputStringIsNull() {
assertThat(charsCount(null), equalTo(Collections.emptyMap())); assertThat(charsCount(null), equalTo(Collections.emptyMap()));
} }
@Test @Test
public void charsCount_shouldReturnEmptyWhenInputStringIsEmpty(){ public void charsCount_shouldReturnEmptyWhenInputStringIsEmpty() {
assertThat(charsCount(""), equalTo(Collections.emptyMap())); assertThat(charsCount(""), equalTo(Collections.emptyMap()));
} }
@Test @Test
public void charsCount_shouldReturnCharsCountWhenInputIsASimpleString(){ public void charsCount_shouldReturnCharsCountWhenInputIsASimpleString() {
Map<Character, Long> expectedOutput = new HashMap<Character, Long>(){{ Map<Character, Long> expectedOutput = new HashMap<Character, Long>() {{
put('a',1L); put('a', 1L);
put('b', 1L); put('b', 1L);
put('c', 1L); put('c', 1L);
}}; }};
assertThat(charsCount("abc"), equalTo(expectedOutput)); assertThat(charsCount("abc"), equalTo(expectedOutput));
} }
@Test @Test
public void charsCount_shouldReturnCharsCountWhenInputIsAComplexString(){ public void charsCount_shouldReturnCharsCountWhenInputIsAComplexString() {
Map<Character, Long> expectedOutput = new HashMap<Character, Long>(){{ Map<Character, Long> expectedOutput = new HashMap<Character, Long>() {{
put('a',1L); put('a', 1L);
put('b', 2L); put('b', 2L);
put('c', 3L); put('c', 3L);
put('A',1L); put('A', 1L);
put('B', 2L); put('B', 2L);
put('C', 3L); put('C', 3L);
put('-', 10L); put('-', 10L);
@@ -1025,19 +1026,42 @@ public class StrmanTest {
assertThat(charsCount("-----abbcccCCCBBA-----"), equalTo(expectedOutput)); assertThat(charsCount("-----abbcccCCCBBA-----"), equalTo(expectedOutput));
} }
@Test @Test
public void isBlank_shouldReturnTrueIfNull() { public void isBlank_shouldReturnTrueIfNull() {
assertTrue(isBlank(null)); assertTrue(isBlank(null));
} }
@Test @Test
public void isBlank_shouldReturnTrueIfEmpty() { public void isBlank_shouldReturnTrueIfEmpty() {
assertTrue(isBlank("")); assertTrue(isBlank(""));
} }
@Test @Test
public void isBlank_shouldReturnFalseIfNotEmpty() { public void isBlank_shouldReturnFalseIfNotEmpty() {
assertFalse(isBlank("ac")); assertFalse(isBlank("ac"));
} }
}
@Test
public void underscored_shouldReturnUnderscoredString() {
assertThat(underscored("MozTransform"), equalTo("moz_transform"));
}
@Test
public void underscored_shouldReturnEmptyStringIfEmptyStringPassedIn() {
assertThat(underscored(""), equalTo(""));
}
@Test
public void underscored_shouldReturnNullIfNullPassedIn() {
assertThat(underscored(null), equalTo(null));
}
@Test
public void underscored_shouldUnderscoreInputString() throws Exception {
assertThat(underscored("foo-bar-baz"), equalTo("foo_bar_baz"));
assertThat(underscored("fooBarBaz"), equalTo("foo_bar_baz"));
assertThat(underscored("FooBarBaz"), equalTo("foo_bar_baz"));
assertThat(underscored(" foo bar baz "), equalTo("foo_bar_baz"));
}
}