28 Commits
Author SHA1 Message Date
Shekhar Gulati 13f0299f2e [Gradle Release Plugin] - pre tag commit: '0.4.0'. 2017-06-30 11:27:10 +05:30
Shekhar Gulati e7343fd155 Resolved #57
This bug is invalid
2017-06-30 11:22:57 +05:30
Shekhar Gulati dee9daee86 Resolved #61
This bug was not valid
2017-06-30 11:19:08 +05:30
Shekhar Gulati a25cba4c63 Resolved #79 2017-06-23 21:23:36 +05:30
Shekhar Gulati db5a8b5d65 Resolved #81 2017-06-23 21:04:12 +05:30
Shekhar Gulati 840198f97c Resolved #85 2017-06-17 05:21:28 +05:30
Shekhar Gulati e39978cb9c Resolved #86.
Also, rewrote underscored implementation to use regex
2017-06-17 05:11:51 +05:30
Shekhar Gulati 88d9664aea Resolved #87 2017-06-17 04:06:46 +05:30
Shekhar Gulati 5e5440119d #88 Added Errorprone to project 2017-06-17 03:50:21 +05:30
Shekhar Gulati f5d9a0b535 #88 Added Checkstyle to project 2017-06-17 03:36:42 +05:30
Shekhar Gulati 5eca5814de Resolved #83 2017-06-17 03:17:05 +05:30
Shekhar Gulati 9b4f0ac791 Code Refactoring
1. Moved all private methods to the end
2. Improved zip implementation so that we leverage Java 8 features
3. Using *Tests convention instead of Test for unit test cases
2017-06-17 03:01:11 +05:30
César Aguilera 90322a7339 Implementation of zip function #72 (#92)
* #72: First test passing

* #72: Second test passing

* #72: Third test passing

* #72: Added extra assertion

* #72: Fixed wrong test

* #72: Fixed wrong test

* #72: Added fourth test (passing)

* #72: fixed typo in test name

* #72: added fifth test

* #72: fixed test names

* #72: refactored for multiple inputs

* #72: added extra test cases and documentation

* #72: addressed @shekhargulati comments
2017-06-14 20:41:54 +05:30
Shekhar Gulati 375da9342d Resolved #84
Merge branch 'deeseja-master'
2017-05-20 23:27:22 +05:30
Shekhar Gulati 4369f904c9 #84 improved implementation of underscored function to incorporate whitespace, dashed strings. Also, cleaned up the code. 2017-05-20 23:24:21 +05:30
Andy Deese d8962a9c7e Merge branch 'master' of https://github.com/deeseja/strman-java 2017-05-20 12:16:12 -04:00
Andy Deese a4d2c2aa41 Added underscored method with tests and documentation 2017-05-20 12:15:20 -04:00
Andy Deese 6bbcb53138 Added underscored method with tests and documentation 2017-05-20 12:01:13 -04:00
Andy Deese d04e679b07 Adding isBlank method (#89)
* added isBlank method, along with junit test and readme update

* removing local files

* adding gitignore with Eclipse specific files ignored

* removed unused imports from Strman.java and split tests out to match current test convention
2017-05-20 06:57:21 +05:30
Andy Deese 04b9f8a7b4 removed unused imports from Strman.java and split tests out to match current test convention 2017-05-19 09:49:13 -04:00
Andy Deese f1e8e83cc0 adding gitignore with Eclipse specific files ignored 2017-05-19 09:28:47 -04:00
Andy Deese fad14c5f40 removing local files 2017-05-19 09:24:56 -04:00
Andy Deese 1877634234 added isBlank method, along with junit test and readme update 2017-05-19 09:18:15 -04:00
Shekhar Gulati cf1d373442 Updated README.md 2017-05-12 16:11:52 +05:30
Shekhar Gulati 7bcc0df6a5 Updated documentation to version 0.3.0 2017-05-12 16:01:33 +05:30
Shekhar Gulati d6dbe785cb Added changelog.md file 2017-05-12 15:43:26 +05:30
Shekhar Gulati 4f0cfaf75b Updated version to 0.3.0 in the README.md file 2017-05-12 15:35:31 +05:30
Shekhar Gulati 33b26a0244 [Gradle Release Plugin] - new version commit: ' 0.4.0-SNAPSHOT'. 2017-05-12 15:26:19 +05:30
11 changed files with 679 additions and 119 deletions
+5
View File
@@ -71,3 +71,8 @@ hs_err_pid*
!gradle/wrapper/gradle-wrapper.jar
/bin/
.classpath
.project
.settings
+88 -3
View File
@@ -1,7 +1,7 @@
strman-java [![Build Status](https://travis-ci.org/shekhargulati/strman-java.svg?branch=master)](https://travis-ci.org/shekhargulati/strman-java) [![codecov.io](https://codecov.io/github/shekhargulati/strman-java/coverage.svg?branch=master)](https://codecov.io/github/shekhargulati/strman-java?branch=master) [![License](https://img.shields.io/:license-mit-blue.svg)](./LICENSE.txt)
------
A Java 8 library for working with String. It is inspired by [dleitee/strman](https://github.com/dleitee/strman).
A Java 8 library for working with String. You can refer to Javadocs online [http://shekhargulati.github.io/strman-java/](http://shekhargulati.github.io/strman-java/).
Getting Started
--------
@@ -15,7 +15,7 @@ For Apache Maven users, please add following to your pom.xml.
<dependency>
<groupId>com.shekhargulati</groupId>
<artifactId>strman</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
</dependency>
</dependencies>
```
@@ -23,9 +23,11 @@ For Apache Maven users, please add following to your pom.xml.
Gradle users can add following to their build.gradle file.
```
compile(group: 'com.shekhargulati', name: 'strman', version: '0.2.0')
compile(group: 'com.shekhargulati', name: 'strman', version: '0.3.0')
```
To learn what we added in the latest version please refer to `./changelog.md`.
## Available Functions
These are the available functions in current version of library:
@@ -80,6 +82,16 @@ chars("title")
// result => ["t", "i", "t", "l", "e"]
```
## charsCount
Counts the number of occurrences of each character in the string
```java
import static strman.Strman.charsCount
charsCount("abca")
// result => Map(("a",2),("b",1),("c",1))
```
## collapseWhitespace
Replace consecutive whitespace characters with a single space.
@@ -496,6 +508,17 @@ transliterate("fóõ bár")
// result => "foo bar"
```
## trimEnd
Removes trailing characters from string.
```
trimEnd(" abc ")
// result => Optional(" abc")
trimEnd("")
// result Optional.empty()
```
## surround
Surrounds a 'value' with the given 'prefix' and 'suffix'.
@@ -559,6 +582,68 @@ toSnakeCase("hello world")
// result => "hello_world"
```
## upperFirst
Converts the first character of string to upper case.
```java
upperFirst("fred")
// result => "Fred"
```
## words
Splits a String to words
```java
words("This is a string, with words!")
// result => ["This", "is", "a", "string", "with", "words"]
```
## isEnclosedBetween
Verifies whether String is enclosed by encloser
```java
isEnclosedBetween("{{shekhar}}", "{{", "}}")
// result => true
```
## join
Join concatenates all the elements of the strings array into a single String. The separator string is placed between elements in the resulting string.
```java
join(new String[]{"hello","world","123"}, ";")
// result => "hello;world;123")
```
## isBlank
isEmpty returns true if a string is blank or null and false otherwise.
```java
isBlank("")
// result => true)
isBlank(null)
// result => true)
isBlank("test")
// result => false)
```
## underscored
`underscored` function converts a camel or dashed string into an underscored one
```java
underscored("MozTransform")
// result => "moz_transform")
```
## Inspiration
This library is inspired by [dleitee/strman](https://github.com/dleitee/strman).
License
-------
strman is licensed under the MIT License - see the `LICENSE` file for details.
+4 -1
View File
@@ -1,5 +1,6 @@
plugins {
id 'net.researchgate.release' version '2.3.3'
id "net.ltgt.errorprone" version "0.0.10"
}
group 'com.shekhargulati'
@@ -9,6 +10,8 @@ apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: "jacoco"
apply from: rootProject.file('gradle/checkstyle.gradle')
apply plugin: "net.ltgt.errorprone"
sourceCompatibility = 1.8
@@ -92,4 +95,4 @@ jacocoTestReport {
}
}
check.dependsOn jacocoTestReport
check.dependsOn jacocoTestReport
+63
View File
@@ -0,0 +1,63 @@
# Version 0.3.0
* __Feature required in #73 (#77)__: Added `charsCount` function
[César Aguilera](mailto:cesar.aguilera.p@gmail.com) - Tue, 9 May 2017 18:16:11 +0530
​
* __fixed bug in containsAll (#76)__
[wli75](mailto:wli75@illinois.edu) - Tue, 7 Mar 2017 20:09:18 +0530
​
* __Resolved #66__: Added `trimEnd` function
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 15:32:45 +0530
​
* __Resolved #65__: Added `trimStart`function
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 15:02:00 +0530
​
* __Resolved #68__: Added `upperFirst` function
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 14:26:16 +0530
​
* __Resolved #69__: Added `words` function
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 12:56:18 +0530
​
* __Resolved#71__: Added `isEnclosedBetween` function
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 12:11:04 +0530
​
* __Resolved #54 and Resolved #59__: Added `capitalize` and `lowerFirst` functions
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 27 Jul 2016 23:19:41 +0530
​
* __Resolved #53__: Added `join` function
[Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Mon, 25 Jul 2016 15:29:43 +0530
​
* __Simplify Maven and Gradle configuration (#70)__
[Marcin Zajączkowski](mailto:mszpak@wp.pl) - Tue, 19 Jul 2016 20:58:57 +0530
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
</suppressions>
+124
View File
@@ -0,0 +1,124 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="com.puppycrawl.tools.checkstyle.Checker">
<!-- Root Checks -->
<module name="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck">
<property name="lineSeparator" value="lf"/>
</module>
<module name="SuppressionFilter">
<property name="file" value="etc/checkstyle-exclude.xml" />
</module>
<!-- TreeWalker Checks -->
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<!-- Annotations -->
<module name="com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck">
<property name="elementStyle" value="compact" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.annotation.MissingOverrideCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.annotation.PackageAnnotationCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck">
<property name="allowSamelineSingleParameterlessAnnotation"
value="false" />
</module>
<!-- Block Checks -->
<module name="com.puppycrawl.tools.checkstyle.checks.blocks.EmptyBlockCheck">
<property name="option" value="text" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.blocks.LeftCurlyCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.blocks.RightCurlyCheck">
<property name="tokens" value="LITERAL_CATCH"/>
<property name="option" value="alone" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.blocks.NeedBracesCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.blocks.AvoidNestedBlocksCheck" />
<!-- Class Design -->
<module name="com.puppycrawl.tools.checkstyle.checks.design.FinalClassCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.design.InterfaceIsTypeCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.design.HideUtilityClassConstructorCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.design.MutableExceptionCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.design.InnerTypeLastCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.design.OneTopLevelClassCheck" />
<!-- Coding -->
<module name="com.puppycrawl.tools.checkstyle.checks.coding.CovariantEqualsCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.EmptyStatementCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.EqualsHashCodeCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.InnerAssignmentCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanExpressionCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.StringLiteralEqualityCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.NestedForDepthCheck">
<property name="max" value="3" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck">
<property name="max" value="3" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.coding.NestedTryDepthCheck">
<property name="max" value="3" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.coding.RequireThisCheck">
<property name="checkMethods" value="false" />
<property name="validateOnlyOverlapping" value="false" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.coding.OneStatementPerLineCheck" />
<!-- Imports -->
<module name="com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck">
<property name="excludes" value="javax.persistence, java.util.stream.Collectors, java.util.*,org.hamcrest.CoreMatchers, org.junit.Assert, strman.Strman"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.imports.RedundantImportCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck">
<property name="processJavadoc" value="true" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck">
<property name="groups" value="java,/^javax?\./,*" />
<property name="ordered" value="true" />
<property name="separated" value="true" />
<property name="option" value="bottom" />
<property name="sortStaticImportsAlphabetically" value="true" />
</module>
<!-- Miscellaneous -->
<module name="com.puppycrawl.tools.checkstyle.checks.indentation.CommentsIndentationCheck">
<property name="tokens" value="BLOCK_COMMENT_BEGIN"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.UpperEllCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.ArrayTypeStyleCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.OuterTypeFilenameCheck" />
<!-- Modifiers -->
<module name="com.puppycrawl.tools.checkstyle.checks.modifier.RedundantModifierCheck" />
<!-- Regexp -->
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="maximum" value="0"/>
<property name="format" value="org\.junit\.Assert\.assert" />
<property name="message"
value="Please use AssertJ imports." />
<property name="ignoreComments" value="true" />
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpCheck">
<property name="format" value="[ \t]+$" />
<property name="illegalPattern" value="true" />
<property name="message" value="Trailing whitespace" />
</module>
<!-- Whitespace -->
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.GenericWhitespaceCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.MethodParamPadCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.NoWhitespaceAfterCheck" >
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS, ARRAY_DECLARATOR"/>
</module>
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.NoWhitespaceBeforeCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.ParenPadCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.TypecastParenPadCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAfterCheck" />
<module name="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck" />
</module>
</module>
+1 -1
View File
@@ -1 +1 @@
version=0.3.0
version= 0.4.0
+10
View File
@@ -0,0 +1,10 @@
apply plugin: 'checkstyle'
checkstyle {
configFile rootProject.file('etc/checkstyle.xml')
showViolations true
}
dependencies {
checkstyle 'com.puppycrawl.tools:checkstyle:7.7'
}
+1 -1
View File
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
+183 -80
View File
@@ -1,4 +1,3 @@
/*
*
* * The MIT License
@@ -27,25 +26,26 @@
package strman;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.*;
/**
* A String manipulation library without any dependencies
*/
public abstract class Strman {
private static final Predicate<String> NULL_STRING_PREDICATE = str -> str == null;
private static final Predicate<String> NULL_STRING_PREDICATE = Objects::isNull;
private static final Supplier<String> NULL_STRING_MSG_SUPPLIER = () -> "'value' should be not null.";
private static final String[] EMPTY_ARRAY = new String[0];
private Strman() {
}
@@ -100,10 +100,6 @@ public abstract class Strman {
return (index < length && index >= 0) ? Optional.of(String.valueOf(value.charAt(index))) : Optional.empty();
}
private static boolean isNullOrEmpty(String input) {
return input == null || input.isEmpty();
}
/**
* Returns an array with strings between start and end.
*
@@ -119,7 +115,8 @@ public abstract class Strman {
validate(end, NULL_STRING_PREDICATE, () -> "'end' should be not null.");
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 +130,6 @@ public abstract class Strman {
return value.split("");
}
/**
* Replace consecutive whitespace characters with a single space.
*
@@ -145,7 +141,6 @@ public abstract class Strman {
return value.trim().replaceAll("\\s\\s+", " ");
}
/**
* Verifies that the needle is contained in the value. The search is case insensitive
*
@@ -242,9 +237,11 @@ public abstract class Strman {
* @param allowOverlapping boolean to take into account overlapping
* @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);
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 +278,8 @@ public abstract class Strman {
* @param caseSensitive 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);
int remainingLength = position - search.length();
if (caseSensitive) {
@@ -327,7 +325,7 @@ public abstract class Strman {
*/
public static String base64Decode(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return new String(Base64.getDecoder().decode(value));
return new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8);
}
/**
@@ -338,7 +336,7 @@ public abstract class Strman {
*/
public static String base64Encode(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return Base64.getEncoder().encodeToString(value.getBytes());
return Base64.getEncoder().encodeToString(value.getBytes(StandardCharsets.UTF_8));
}
/**
@@ -435,7 +433,7 @@ public abstract class Strman {
*/
public static String format(final String value, String... params) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
Pattern p = Pattern.compile("\\{(\\w+)\\}");
Pattern p = Pattern.compile("\\{(\\w+)}");
Matcher m = p.matcher(value);
String result = value;
while (m.find()) {
@@ -640,7 +638,8 @@ public abstract class Strman {
* @param caseSensitive whether search should be case sensitive
* @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(needle, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
if (caseSensitive) {
@@ -775,7 +774,8 @@ public abstract class Strman {
public static String removeRight(final String value, final String suffix, final boolean caseSensitive) {
validate(value, 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 +810,15 @@ public abstract class Strman {
* @param caseSensitive whether search should be case sensitive or not
* @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(search, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
if (caseSensitive) {
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));
}
/**
@@ -907,10 +909,22 @@ public abstract class Strman {
* @return Words Array
*/
public static String[] words(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return value.split("\\W+");
return words(value, "\\s+");
}
/**
* Splits a String to words by delimiter, \s+ by default
*
* @param value The input String
* @param delimiter delimiter for splitting input String
* @return words array
*/
public static String[] words(final String value, final String delimiter) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return value.split(delimiter);
}
/**
* Truncate the unsecured form string, cutting the independent string of required position.
*
@@ -950,11 +964,8 @@ public abstract class Strman {
*/
public static String htmlEncode(final String html) {
validate(html, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return html
.chars()
.mapToObj(c -> "\\u" + String.format("%04x", c).toUpperCase())
.map(HtmlEntities.encodedEntities::get)
.collect(joining());
return html.chars().mapToObj(c -> "\\u" + String.format("%04x", c).toUpperCase())
.map(HtmlEntities.encodedEntities::get).collect(joining());
}
/**
@@ -998,7 +1009,7 @@ public abstract class Strman {
public static String slugify(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
String transliterated = transliterate(collapseWhitespace(value.trim().toLowerCase()));
return Arrays.stream(words(transliterated.replace("&", "-and-"))).collect(joining("-"));
return Arrays.stream(words(transliterated.replace("&", "-and-"), "\\W+")).collect(joining("-"));
}
/**
@@ -1019,7 +1030,6 @@ public abstract class Strman {
return result;
}
/**
* Surrounds a 'value' with the given 'prefix' and 'suffix'.
*
@@ -1041,7 +1051,9 @@ public abstract class Strman {
* @return String in camelCase.
*/
public static String toCamelCase(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
if (value == null || value.length() == 0) {
return "";
}
String str = toStudlyCase(value);
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
@@ -1055,10 +1067,7 @@ public abstract class Strman {
public static String toStudlyCase(final String value) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
String[] words = collapseWhitespace(value.trim()).split("\\s*(_|-|\\s)\\s*");
return Arrays.stream(words)
.filter(w -> !w.trim().isEmpty())
.map(Strman::upperFirst)
.collect(joining());
return Arrays.stream(words).filter(w -> !w.trim().isEmpty()).map(Strman::upperFirst).collect(joining());
}
/**
@@ -1106,8 +1115,7 @@ public abstract class Strman {
public static String decode(final String value, final int digits, final int radix) {
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
return Arrays
.stream(value.split("(?<=\\G.{" + digits + "})"))
return Arrays.stream(value.split("(?<=\\G.{" + digits + "})"))
.map(data -> String.valueOf(Character.toChars(Integer.parseInt(data, radix))))
.collect(joining());
}
@@ -1117,7 +1125,6 @@ public abstract class Strman {
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.
*
@@ -1152,11 +1159,7 @@ public abstract class Strman {
if (input.length() == 0) {
return "";
}
return head(input)
.map(String::toUpperCase)
.map(h ->
tail(input).map(t -> h + t.toLowerCase()).orElse(h))
.get();
return head(input).map(String::toUpperCase).map(h -> tail(input).map(t -> h + t.toLowerCase()).orElse(h)).get();
}
/**
@@ -1164,7 +1167,6 @@ public abstract class Strman {
*
* @param input The string to convert
* @return The converted string
* @throws IllegalArgumentException
*/
public static String lowerFirst(final String input) throws IllegalArgumentException {
if (input == null) {
@@ -1174,11 +1176,7 @@ public abstract class Strman {
return "";
}
return head(input)
.map(String::toLowerCase)
.map(h ->
tail(input).map(t -> h + t).orElse(h))
.get();
return head(input).map(String::toLowerCase).map(h -> tail(input).map(t -> h + t).orElse(h)).get();
}
/**
@@ -1223,10 +1221,7 @@ public abstract class Strman {
if (input == null) {
throw new IllegalArgumentException("input can't be null");
}
return head(input)
.map(String::toUpperCase)
.map(h -> tail(input).map(t -> h + t).orElse(h))
.get();
return head(input).map(String::toUpperCase).map(h -> tail(input).map(t -> h + t).orElse(h)).get();
}
/**
@@ -1236,27 +1231,21 @@ public abstract class Strman {
* @return Returns the trimmed string.
*/
public static Optional<String> trimStart(final String input) {
return Optional.ofNullable(input)
.filter(v -> !v.isEmpty())
.map(Strman::leftTrim);
return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(Strman::leftTrim);
}
/**
* Removes leading characters from string.
*
* @param input The string to trim.
* @param chars The characters to trim.
*
* @return Returns the trimmed string.
*/
public static Optional<String> trimStart(final String input, String... chars) {
return Optional.ofNullable(input)
.filter(v -> !v.isEmpty())
.map(v -> {
String pattern = String.format("^[%s]+", join(chars, "\\"));
return v.replaceAll(pattern, "");
});
return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(v -> {
String pattern = String.format("^[%s]+", join(chars, "\\"));
return v.replaceAll(pattern, "");
});
}
/**
@@ -1266,30 +1255,23 @@ public abstract class Strman {
* @return Returns the trimmed string.
*/
public static Optional<String> trimEnd(final String input) {
return Optional.ofNullable(input)
.filter(v -> !v.isEmpty())
.map(Strman::rightTrim);
return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(Strman::rightTrim);
}
/**
* Removes trailing characters from string.
*
* @param input The string to trim.
* @param chars The characters to trim.
*
* @return Returns the trimmed string.
*/
public static Optional<String> trimEnd(final String input, String... chars) {
return Optional.ofNullable(input)
.filter(v -> !v.isEmpty())
.map(v -> {
String pattern = String.format("[%s]+$", join(chars, "\\"));
return v.replaceAll(pattern, "");
});
return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(v -> {
String pattern = String.format("[%s]+$", join(chars, "\\"));
return v.replaceAll(pattern, "");
});
}
/**
* Counts the number of occurrences of each character in the string
*
@@ -1301,9 +1283,125 @@ public abstract class Strman {
return Collections.emptyMap();
}
return input.chars()
.mapToObj(c -> (char) c)
.collect(groupingBy(identity(), counting()));
return input.chars().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.
*
* @param input The input string
* @return true if input string is null or empty
*/
public static boolean isBlank(String input) {
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 || input.length() == 0) {
return "";
}
return input.trim().replaceAll("([a-z\\d])([A-Z]+)", "$1_$2").replaceAll("[-\\s]+", "_").toLowerCase();
}
/**
* Aggregates the contents of n strings into a single list of tuples.
*
* @param inputs A list of strings.
* @return A list of strings if none of the strings in the input is null or empty.
* An empty list otherwise.
*/
public static List<String> zip(String... inputs) {
if (inputs.length == 0) {
return Collections.emptyList();
}
OptionalInt min = Arrays.stream(inputs).mapToInt(str -> str == null ? 0 : str.length()).min();
if (!min.isPresent()) {
return Collections.emptyList();
}
return IntStream.range(0, min.getAsInt())
.mapToObj(elementIndex -> Arrays.stream(inputs)
.map(input -> String.valueOf(input.charAt(elementIndex)))
.collect(joining()))
.collect(toList());
}
/**
* Split lines to an array
*
* @param input The input String
* @return lines in an array
*/
public static String[] lines(String input) {
if (input == null) {
return EMPTY_ARRAY;
}
return input.split("\r\n?|\n");
}
/**
* Converts a underscored or camelized string into an dasherized one.
*
* @param input The input String
* @return dasherized String.
*/
public static String dasherize(String input) {
return toKebabCase(input);
}
/**
* Converts an underscored, camelized, or dasherized string into a humanized one. Also removes beginning and ending whitespace.
*
* @param input The input String
* @return humanized version of String
*/
public static String humanize(final String input) {
if (input == null || input.length() == 0) {
return "";
}
return upperFirst(underscored(input).replaceAll("_", " "));
}
/**
* Returns a copy of the string in which all the case-based characters have had their case swapped.
*
* @param input Input string
* @return String with all the case swapped
*/
public static String swapCase(String input) {
if (input == null || input.length() == 0) {
return "";
}
StringBuilder resultBuilder = new StringBuilder();
for (char ch : input.toCharArray()) {
if (Character.isUpperCase(ch)) {
resultBuilder.append(Character.toLowerCase(ch));
} else {
resultBuilder.append(Character.toUpperCase(ch));
}
}
return resultBuilder.toString();
}
public static String[] chop(String input, int step) {
if (input == null || input.length() == 0) {
return EMPTY_ARRAY;
}
if (step == 0) {
return new String[]{input};
}
int strLength = input.length();
int iterations = strLength % step == 0 ? strLength / step : strLength / step + 1;
return IntStream.iterate(0, i -> i + step)
.limit(iterations)
.mapToObj(i -> input.substring(i, (i + step) < strLength ? i + step : strLength))
.toArray(String[]::new);
}
private static void validate(String value, Predicate<String> predicate, final Supplier<String> supplier) {
@@ -1325,5 +1423,10 @@ public abstract class Strman {
}
return countSubstr(value.substring(offset), subStr, allowOverlapping, ++count);
}
private static boolean isNullOrEmpty(String input) {
return input == null || input.isEmpty();
}
}
@@ -26,21 +26,29 @@
package strman;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.junit.Ignore;
import org.junit.Test;
import java.util.*;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.collection.IsArrayContaining.hasItemInArray;
import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining;
import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize;
import static org.hamcrest.collection.IsArrayWithSize.emptyArray;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.junit.Assert.*;
import static strman.Strman.*;
import static strman.Strman.endsWith;
import static strman.Strman.format;
public class StrmanTest {
public class StrmanTests {
@Test
public void append_shouldAppendStringsToEndOfValue() throws Exception {
@@ -821,6 +829,18 @@ public class StrmanTest {
Arrays.stream(fixture).forEach(el -> assertThat(String.format("toSnakeCase(%s) should be de_camelize", el), toSnakeCase(el), equalTo("de_camelize")));
}
@Test
public void snakeCase_shouldConvertAStringToSnakecase() throws Exception {
String[] input = {
"Foo Bar",
"fooBar"
};
Arrays.stream(input).forEach(el ->
assertThat(String.format("%s should be foo_bar", el), toSnakeCase(el), is(equalTo("foo_bar"))));
}
@Test
public void unequal_shouldTestInequalityOfStrings() throws Exception {
assertThat(unequal("a", "b"), equalTo(true));
@@ -859,12 +879,11 @@ public class StrmanTest {
assertThat(result, is(equalTo("fred, barney, &amp; pebbles")));
}
@Ignore
@Test
public void kebabCase_shouldConvertAStringToKebabCase() throws Exception {
String[] input = {
"Foo Bar",
"fooBar",
"__FOO_BAR__"
"fooBar"
};
Arrays.stream(input).forEach(el ->
@@ -872,19 +891,6 @@ public class StrmanTest {
}
@Ignore
public void snakeCase_shouldConvertAStringToSnakecase() throws Exception {
String[] input = {
"Foo Bar",
"fooBar",
"--FOO-BAR--"
};
Arrays.stream(input).forEach(el ->
assertThat(String.format("%s should be foo_bar", el), toSnakeCase(el), is(equalTo("foo_bar"))));
}
@Test
public void join_shouldJoinArrayOfStringIntoASingleString() throws Exception {
String[] strings = {
@@ -945,7 +951,7 @@ public class StrmanTest {
@Test
public void words_shouldConvertTextToWords() throws Exception {
final String line = "This is a string, with words!";
assertThat(words(line), is(new String[]{"This", "is", "a", "string", "with", "words"}));
assertThat(words(line), arrayContaining("This", "is", "a", "string,", "with", "words!"));
}
@Test
@@ -992,34 +998,34 @@ public class StrmanTest {
@Test
public void charsCount_shouldReturnEmptyWhenInputStringIsNull(){
public void charsCount_shouldReturnEmptyWhenInputStringIsNull() {
assertThat(charsCount(null), equalTo(Collections.emptyMap()));
}
@Test
public void charsCount_shouldReturnEmptyWhenInputStringIsEmpty(){
public void charsCount_shouldReturnEmptyWhenInputStringIsEmpty() {
assertThat(charsCount(""), equalTo(Collections.emptyMap()));
}
@Test
public void charsCount_shouldReturnCharsCountWhenInputIsASimpleString(){
Map<Character, Long> expectedOutput = new HashMap<Character, Long>(){{
put('a',1L);
put('b', 1L);
put('c', 1L);
public void charsCount_shouldReturnCharsCountWhenInputIsASimpleString() {
Map<Character, Long> expectedOutput = new HashMap<Character, Long>() {{
put('a', 1L);
put('b', 1L);
put('c', 1L);
}};
assertThat(charsCount("abc"), equalTo(expectedOutput));
}
@Test
public void charsCount_shouldReturnCharsCountWhenInputIsAComplexString(){
Map<Character, Long> expectedOutput = new HashMap<Character, Long>(){{
put('a',1L);
public void charsCount_shouldReturnCharsCountWhenInputIsAComplexString() {
Map<Character, Long> expectedOutput = new HashMap<Character, Long>() {{
put('a', 1L);
put('b', 2L);
put('c', 3L);
put('A',1L);
put('A', 1L);
put('B', 2L);
put('C', 3L);
put('-', 10L);
@@ -1027,4 +1033,157 @@ public class StrmanTest {
assertThat(charsCount("-----abbcccCCCBBA-----"), equalTo(expectedOutput));
}
}
@Test
public void isBlank_shouldReturnTrueIfNull() {
assertTrue(isBlank(null));
}
@Test
public void isBlank_shouldReturnTrueIfEmpty() {
assertTrue(isBlank(""));
}
@Test
public void isBlank_shouldReturnFalseIfNotEmpty() {
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(""));
}
@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"));
}
@Test
public void zip_shouldReturnEmptyList_whenNullOrEmptyIsPassedIn() {
assertThat(zip("a", null), is(empty()));
assertThat(zip("", "a"), is(empty()));
}
@Test
public void zip_shouldReturnListOfOneElement_forSimplestValidInput() {
assertThat(zip("a", "b"), equalTo(asList("ab")));
}
@Test
public void zip_shouldReturnExpectedListOfPairs_whenBothInputsHaveSameSize() {
assertThat(zip("abc", "def"), equalTo(asList("ad", "be", "cf")));
assertThat(zip("ABC", "DEF"), equalTo(asList("AD", "BE", "CF")));
}
@Test
public void zip_shouldReturnExpectedListOfPairs_whenFirstInputIsBiggerThanSecond() {
assertThat(zip("abc", "d"), equalTo(asList("ad")));
assertThat(zip("ABCDE", "FGH"), equalTo(asList("AF", "BG", "CH")));
}
@Test
public void zip_shouldReturnExpectedListOfPairs_whenSecondInputIsBiggerThanFirst() {
assertThat(zip("d", "abc"), equalTo(asList("da")));
assertThat(zip("FGH", "ABCDE"), equalTo(asList("FA", "GB", "HC")));
}
@Test
public void zip_shouldReturnExpectedListOfTriplets_whenThreeInputs() {
assertThat(zip("abc", "def", "ghi"), equalTo(asList("adg", "beh", "cfi")));
}
@Test
public void zip_shouldReturnExpectedListOfTuples_whenMoreThanThreeInputs() {
assertThat(zip("abc", "def", "ghi", "123"), equalTo(asList("adg1", "beh2", "cfi3")));
}
@Test
public void zip_shouldReturnEmptyList_whenNotEnoughInputs() {
assertThat(zip(), is(empty()));
}
@Test
public void zip_shouldReturnInputInListForm_whenOnlyOneInput() {
assertThat(zip("zip"), is(equalTo(asList("z", "i", "p"))));
assertThat(zip("z"), is(equalTo(singletonList("z"))));
}
@Test
public void lines_shouldReturnEmptyArrayWhenInputIsNull() throws Exception {
assertThat(lines(null), emptyArray());
}
@Test
public void lines_shouldReturnArrayWithOneEmptyElementWhenInputIsEmptyString() throws Exception {
assertThat(lines(""), arrayWithSize(1));
assertThat(lines(""), hasItemInArray(""));
}
@Test
public void lines_shouldSplitToLines() throws Exception {
assertThat(lines("Hello\r\nWorld").length, equalTo(2));
assertThat(lines("Hello\rWorld").length, equalTo(2));
assertThat(lines("Hello World").length, equalTo(1));
assertThat(lines("\r\n\n\r ").length, equalTo(4));
assertThat(lines("Hello\r\r\nWorld").length, equalTo(3));
assertThat(lines("Hello\r\rWorld").length, equalTo(3));
}
@Test
public void humanize_shouldHumanizeStrings() throws Exception {
assertThat(humanize("the_humanize_method"), equalTo("The humanize method"));
assertThat(humanize("ThehumanizeMethod"), equalTo("Thehumanize method"));
assertThat(humanize("ThehumanizeMethod"), equalTo("Thehumanize method"));
assertThat(humanize("the humanize method"), equalTo("The humanize method"));
assertThat(humanize("the humanize_id method_id"), equalTo("The humanize id method id"));
assertThat(humanize("the humanize method "), equalTo("The humanize method"));
assertThat(humanize(" capitalize dash-CamelCase_underscore trim "), equalTo("Capitalize dash camel case underscore trim"));
assertThat(humanize(""), equalTo(""));
assertThat(humanize(null), equalTo(""));
}
@Test
public void dasherize_shouldDasherizeInputString() throws Exception {
assertThat(dasherize("the_dasherize_string_method"), equalTo("the-dasherize-string-method"));
assertThat(dasherize("TheDasherizeStringMethod"), equalTo("the-dasherize-string-method"));
assertThat(dasherize("thisIsATest"), equalTo("this-is-a-test"));
assertThat(dasherize("this Is A Test"), equalTo("this-is-a-test"));
assertThat(dasherize("thisIsATest123"), equalTo("this-is-a-test123"));
assertThat(dasherize("123thisIsATest"), equalTo("123this-is-a-test"));
assertThat(dasherize("the dasherize string method"), equalTo("the-dasherize-string-method"));
assertThat(dasherize("the dasherize string method "), equalTo("the-dasherize-string-method"));
assertThat(dasherize("input with a-dash"), equalTo("input-with-a-dash"));
assertThat(dasherize(""), equalTo(""));
assertThat(dasherize(null), equalTo(""));
}
@Test
public void swapCase_shouldSwapCaseOfCharacters() throws Exception {
assertThat(swapCase("AaBbCcDdEe"), equalTo("aAbBcCdDeE"));
assertThat(swapCase("Hello World"), equalTo("hELLO wORLD"));
assertThat(swapCase(""), equalTo(""));
assertThat(swapCase(null), equalTo(""));
}
@Test
public void chop_shouldChopStringByStep() throws Exception {
assertThat(chop(null, 2).length, equalTo(0));
assertThat(chop("whitespace", 2).length, equalTo(5));
assertThat(chop("whitespace", 3).length, equalTo(4));
assertThat(chop("whitespace", 0)[0].length(), equalTo(10));
}
}