├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── build.gradle ├── changelog.md ├── etc ├── checkstyle-exclude.xml └── checkstyle.xml ├── gradle.properties ├── gradle ├── checkstyle.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main └── java │ └── strman │ ├── Ascii.java │ ├── HtmlEntities.java │ └── Strman.java └── test └── java └── strman └── StrmanTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 4 | 5 | *.iml 6 | 7 | ## Directory-based project format: 8 | .idea/ 9 | # if you remove the above rule, at least ignore the following: 10 | 11 | # User-specific stuff: 12 | # .idea/workspace.xml 13 | # .idea/tasks.xml 14 | # .idea/dictionaries 15 | 16 | # Sensitive or high-churn files: 17 | # .idea/dataSources.ids 18 | # .idea/dataSources.xml 19 | # .idea/sqlDataSources.xml 20 | # .idea/dynamic.xml 21 | # .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | # .idea/gradle.xml 25 | # .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | # .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.ipr 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | /out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | ### Gradle template 50 | .gradle 51 | build/ 52 | 53 | # Ignore Gradle GUI config 54 | gradle-app.setting 55 | 56 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 57 | !gradle-wrapper.jar 58 | ### Java template 59 | *.class 60 | 61 | # Mobile Tools for Java (J2ME) 62 | .mtj.tmp/ 63 | 64 | # Package Files # 65 | *.jar 66 | *.war 67 | *.ear 68 | 69 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 70 | hs_err_pid* 71 | 72 | !gradle/wrapper/gradle-wrapper.jar 73 | 74 | /bin/ 75 | 76 | .classpath 77 | .project 78 | .settings 79 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | install: ./gradlew assemble -x :signArchives 3 | script: ./gradlew clean build -x :signArchives 4 | jdk: 5 | - oraclejdk8 6 | after_success: 7 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2016 Shekhar Gulati . 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 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) 2 | ------ 3 | 4 | A Java 8 library for working with Strings. 5 | You can learn about all the String utility functions implemented in `strman` library by reading the [documentation](https://github.com/shekhargulati/strman-java/wiki). 6 | 7 | Getting Started 8 | -------- 9 | 10 | To use strman in your application, you have to add `strman` to your classpath. 11 | strman is available on [Maven Central](http://search.maven.org/) so you just need to add dependency in your favorite build tool as shown below. 12 | 13 | For Apache Maven users, please add following to your `pom.xml`. 14 | 15 | ```xml 16 | 17 | 18 | com.shekhargulati 19 | strman 20 | 0.4.0 21 | 22 | 23 | ``` 24 | 25 | Gradle users can add following to their `build.gradle` file. 26 | 27 | ``` 28 | compile(group: 'com.shekhargulati', name: 'strman', version: '0.4.0') 29 | ``` 30 | 31 | To learn what we added in the latest version please refer to `./changelog.md`. 32 | 33 | You can refer to Javadocs online [http://shekhargulati.github.io/strman-java/](http://shekhargulati.github.io/strman-java/). 34 | 35 | ## Inspiration 36 | 37 | This library is inspired by [dleitee/strman](https://github.com/dleitee/strman). 38 | 39 | License 40 | ------- 41 | strman is licensed under the MIT License - see the `LICENSE` file for details. 42 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'net.researchgate.release' version '2.3.3' 3 | id "net.ltgt.errorprone" version "0.0.10" 4 | } 5 | 6 | group 'com.shekhargulati' 7 | 8 | apply plugin: 'java' 9 | apply plugin: 'maven' 10 | apply plugin: 'maven-publish' 11 | apply plugin: 'signing' 12 | apply plugin: "jacoco" 13 | apply from: rootProject.file('gradle/checkstyle.gradle') 14 | apply plugin: "net.ltgt.errorprone" 15 | 16 | sourceCompatibility = 1.8 17 | 18 | repositories { 19 | mavenCentral() 20 | } 21 | 22 | dependencies { 23 | 24 | testCompile group: 'junit', name: 'junit', version: '4.11' 25 | testCompile 'org.hamcrest:hamcrest-all:1.3' 26 | } 27 | 28 | 29 | uploadArchives { 30 | repositories { 31 | mavenDeployer { 32 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 33 | 34 | repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { 35 | authentication(userName: System.getenv('OSS_USER'), password: System.getenv('OSS_PASSWORD')) 36 | } 37 | 38 | snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { 39 | authentication(userName: System.getenv('OSS_USER'), password: System.getenv('OSS_PASSWORD')) 40 | } 41 | 42 | pom.project { 43 | name 'strman' 44 | packaging 'jar' 45 | artifactId 'strman' 46 | description 'A Java 8 library for working with String' 47 | url 'https://github.com/shekhargulati/strman-java' 48 | 49 | scm { 50 | connection 'https://github.com/shekhargulati/strman-java.git' 51 | developerConnection 'https://github.com/shekhargulati/strman-java.git' 52 | url 'https://github.com/shekhargulati/strman-java.git' 53 | } 54 | 55 | licenses { 56 | license { 57 | name 'MIT' 58 | } 59 | } 60 | 61 | developers { 62 | developer { 63 | id 'shekhargulati' 64 | name 'Shekhar Gulati' 65 | email 'shekhargulati84@gmail.com' 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | 73 | task javadocJar(type: Jar) { 74 | classifier = 'javadoc' 75 | from javadoc 76 | } 77 | 78 | task sourcesJar(type: Jar) { 79 | classifier = 'sources' 80 | from sourceSets.main.allSource 81 | } 82 | 83 | artifacts { 84 | archives javadocJar, sourcesJar 85 | } 86 | 87 | signing { 88 | sign configurations.archives 89 | } 90 | 91 | jacocoTestReport { 92 | reports { 93 | xml.enabled = true 94 | html.enabled = true 95 | } 96 | } 97 | 98 | check.dependsOn jacocoTestReport 99 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Version 0.3.0 2 | 3 | 4 | * __Feature required in #73 (#77)__: Added `charsCount` function 5 | 6 | [César Aguilera](mailto:cesar.aguilera.p@gmail.com) - Tue, 9 May 2017 18:16:11 +0530 7 | 8 | ​ 9 | 10 | * __fixed bug in containsAll (#76)__ 11 | 12 | [wli75](mailto:wli75@illinois.edu) - Tue, 7 Mar 2017 20:09:18 +0530 13 | 14 | ​ 15 | 16 | * __Resolved #66__: Added `trimEnd` function 17 | 18 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 15:32:45 +0530 19 | 20 | ​ 21 | 22 | * __Resolved #65__: Added `trimStart`function 23 | 24 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 15:02:00 +0530 25 | 26 | ​ 27 | 28 | * __Resolved #68__: Added `upperFirst` function 29 | 30 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 14:26:16 +0530 31 | 32 | ​ 33 | 34 | * __Resolved #69__: Added `words` function 35 | 36 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 12:56:18 +0530 37 | 38 | ​ 39 | 40 | * __Resolved#71__: Added `isEnclosedBetween` function 41 | 42 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 24 Aug 2016 12:11:04 +0530 43 | 44 | ​ 45 | 46 | * __Resolved #54 and Resolved #59__: Added `capitalize` and `lowerFirst` functions 47 | 48 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Wed, 27 Jul 2016 23:19:41 +0530 49 | 50 | ​ 51 | 52 | * __Resolved #53__: Added `join` function 53 | 54 | [Shekhar Gulati](mailto:shekhargulati84@gmail.com) - Mon, 25 Jul 2016 15:29:43 +0530 55 | 56 | ​ 57 | 58 | * __Simplify Maven and Gradle configuration (#70)__ 59 | 60 | [Marcin Zajączkowski](mailto:mszpak@wp.pl) - Tue, 19 Jul 2016 20:58:57 +0530 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /etc/checkstyle-exclude.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version= 0.5.0-SNAPSHOT -------------------------------------------------------------------------------- /gradle/checkstyle.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'checkstyle' 2 | 3 | checkstyle { 4 | configFile rootProject.file('etc/checkstyle.xml') 5 | showViolations true 6 | } 7 | 8 | dependencies { 9 | checkstyle 'com.puppycrawl.tools:checkstyle:7.7' 10 | } 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shekhargulati/strman-java/d0c2a10a6273fd6082f084e95156653ca55ce1be/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue May 03 18:47:15 IST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'strman' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/strman/Ascii.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * The MIT License 4 | * * 5 | * * Copyright 2016 Shekhar Gulati . 6 | * * 7 | * * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * * of this software and associated documentation files (the "Software"), to deal 9 | * * in the Software without restriction, including without limitation the rights 10 | * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * * copies of the Software, and to permit persons to whom the Software is 12 | * * furnished to do so, subject to the following conditions: 13 | * * 14 | * * The above copyright notice and this permission notice shall be included in 15 | * * all copies or substantial portions of the Software. 16 | * * 17 | * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | package strman; 28 | 29 | import java.util.Arrays; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | import java.util.Map; 33 | 34 | abstract class Ascii { 35 | public static final Map> ascii = new HashMap>() {{ 36 | 37 | put("0", Arrays.asList("°", "₀", "۰")); 38 | put("1", Arrays.asList("¹", "₁", "۱")); 39 | put("2", Arrays.asList("²", "₂", "۲")); 40 | put("3", Arrays.asList("³", "₃", "۳")); 41 | put("4", Arrays.asList("⁴", "₄", "۴", "٤")); 42 | put("5", Arrays.asList("⁵", "₅", "۵", "٥")); 43 | put("6", Arrays.asList("⁶", "₆", "۶", "٦")); 44 | put("7", Arrays.asList("⁷", "₇", "۷")); 45 | put("8", Arrays.asList("⁸", "₈", "۸")); 46 | put("9", Arrays.asList("⁹", "₉", "۹")); 47 | put("a", Arrays.asList("à", "á", "ả", "ã", "ạ", "ă", "ắ", "ằ", "ẳ", "ẵ", "ặ", "â", "ấ", "ầ", "ẩ", "ẫ", "ậ", 48 | "ā", "ą", "å", "α", "ά", "ἀ", "ἁ", "ἂ", "ἃ", "ἄ", "ἅ", "ἆ", "ἇ", "ᾀ", "ᾁ", "ᾂ", "ᾃ", 49 | "ᾄ", "ᾅ", "ᾆ", "ᾇ", "ὰ", "ά", "ᾰ", "ᾱ", "ᾲ", "ᾳ", "ᾴ", "ᾶ", "ᾷ", "а", "أ", "အ", "ာ", 50 | "ါ", "ǻ", "ǎ", "ª", "ა", "अ", "ا")); 51 | put("b", Arrays.asList("б", "β", "Ъ", "Ь", "ب", "ဗ", "ბ")); 52 | put("c", Arrays.asList("ç", "ć", "č", "ĉ", "ċ")); 53 | put("d", Arrays.asList("ď", "ð", "đ", "ƌ", "ȡ", "ɖ", "ɗ", "ᵭ", "ᶁ", "ᶑ", "д", "δ", "د", "ض", "ဍ", "ဒ", "დ")); 54 | put("e", Arrays.asList("é", "è", "ẻ", "ẽ", "ẹ", "ê", "ế", "ề", "ể", "ễ", "ệ", "ë", "ē", "ę", "ě", "ĕ", "ė", 55 | "ε", "έ", "ἐ", "ἑ", "ἒ", "ἓ", "ἔ", "ἕ", "ὲ", "έ", "е", "ё", "э", "є", "ə", "ဧ", "ေ", 56 | "ဲ", "ე", "ए", "إ", "ئ")); 57 | put("f", Arrays.asList("ф", "φ", "ف", "ƒ", "ფ")); 58 | put("g", Arrays.asList("ĝ", "ğ", "ġ", "ģ", "г", "ґ", "γ", "ဂ", "გ", "گ")); 59 | put("h", Arrays.asList("ĥ", "ħ", "η", "ή", "ح", "ه", "ဟ", "ှ", "ჰ")); 60 | put("i", Arrays.asList("í", "ì", "ỉ", "ĩ", "ị", "î", "ï", "ī", "ĭ", "į", "ı", "ι", "ί", "ϊ", "ΐ", "ἰ", "ἱ", 61 | "ἲ", "ἳ", "ἴ", "ἵ", "ἶ", "ἷ", "ὶ", "ί", "ῐ", "ῑ", "ῒ", "ΐ", "ῖ", "ῗ", "і", "ї", "и", 62 | "ဣ", "ိ", "ီ", "ည်", "ǐ", "ი", "इ", "ی")); 63 | put("j", Arrays.asList("ĵ", "ј", "Ј", "ჯ", "ج")); 64 | put("k", Arrays.asList("ķ", "ĸ", "к", "κ", "Ķ", "ق", "ك", "က", "კ", "ქ", "ک")); 65 | put("l", Arrays.asList("ł", "ľ", "ĺ", "ļ", "ŀ", "л", "λ", "ل", "လ", "ლ")); 66 | put("m", Arrays.asList("м", "μ", "م", "မ", "მ")); 67 | put("n", Arrays.asList("ñ", "ń", "ň", "ņ", "ʼn", "ŋ", "ν", "н", "ن", "န", "ნ")); 68 | put("o", Arrays.asList("ó", "ò", "ỏ", "õ", "ọ", "ô", "ố", "ồ", "ổ", "ỗ", "ộ", "ơ", "ớ", "ờ", "ở", "ỡ", "ợ", 69 | "ø", "ō", "ő", "ŏ", "ο", "ὀ", "ὁ", "ὂ", "ὃ", "ὄ", "ὅ", "ὸ", "ό", "о", "و", "θ", "ို", 70 | "ǒ", "ǿ", "º", "ო", "ओ")); 71 | put("p", Arrays.asList("п", "π", "ပ", "პ", "پ")); 72 | put("q", Arrays.asList("ყ")); 73 | put("r", Arrays.asList("ŕ", "ř", "ŗ", "р", "ρ", "ر", "რ")); 74 | put("s", Arrays.asList("ś", "š", "ş", "с", "σ", "ș", "ς", "س", "ص", "စ", "ſ", "ს")); 75 | put("t", Arrays.asList("ť", "ţ", "т", "τ", "ț", "ت", "ط", "ဋ", "တ", "ŧ", "თ", "ტ")); 76 | put("u", Arrays.asList("ú", "ù", "ủ", "ũ", "ụ", "ư", "ứ", "ừ", "ử", "ữ", "ự", "û", "ū", "ů", "ű", "ŭ", "ų", 77 | "µ", "у", "ဉ", "ု", "ူ", "ǔ", "ǖ", "ǘ", "ǚ", "ǜ", "უ", "उ")); 78 | put("v", Arrays.asList("в", "ვ", "ϐ")); 79 | put("w", Arrays.asList("ŵ", "ω", "ώ", "ဝ", "ွ")); 80 | put("x", Arrays.asList("χ", "ξ")); 81 | put("y", Arrays.asList("ý", "ỳ", "ỷ", "ỹ", "ỵ", "ÿ", "ŷ", "й", "ы", "υ", "ϋ", "ύ", "ΰ", "ي", "ယ")); 82 | put("z", Arrays.asList("ź", "ž", "ż", "з", "ζ", "ز", "ဇ", "ზ")); 83 | put("aa", Arrays.asList("ع", "आ", "آ")); 84 | put("ae", Arrays.asList("ä", "æ", "ǽ")); 85 | put("ai", Arrays.asList("ऐ")); 86 | put("at", Arrays.asList("@")); 87 | put("ch", Arrays.asList("ч", "ჩ", "ჭ", "چ")); 88 | put("dj", Arrays.asList("ђ", "đ")); 89 | put("dz", Arrays.asList("џ", "ძ")); 90 | put("ei", Arrays.asList("ऍ")); 91 | put("gh", Arrays.asList("غ", "ღ")); 92 | put("ii", Arrays.asList("ई")); 93 | put("ij", Arrays.asList("ij")); 94 | put("kh", Arrays.asList("х", "خ", "ხ")); 95 | put("lj", Arrays.asList("љ")); 96 | put("nj", Arrays.asList("њ")); 97 | put("oe", Arrays.asList("ö", "œ", "ؤ")); 98 | put("oi", Arrays.asList("ऑ")); 99 | put("oii", Arrays.asList("ऒ")); 100 | put("ps", Arrays.asList("ψ")); 101 | put("sh", Arrays.asList("ш", "შ", "ش")); 102 | put("shch", Arrays.asList("щ")); 103 | put("ss", Arrays.asList("ß")); 104 | put("sx", Arrays.asList("ŝ")); 105 | put("th", Arrays.asList("þ", "ϑ", "ث", "ذ", "ظ")); 106 | put("ts", Arrays.asList("ц", "ც", "წ")); 107 | put("ue", Arrays.asList("ü")); 108 | put("uu", Arrays.asList("ऊ")); 109 | put("ya", Arrays.asList("я")); 110 | put("yu", Arrays.asList("ю")); 111 | put("zh", Arrays.asList("ж", "ჟ", "ژ")); 112 | put("(c)", Arrays.asList("©")); 113 | put("A", Arrays.asList("Á", "À", "Ả", "Ã", "Ạ", "Ă", "Ắ", "Ằ", "Ẳ", "Ẵ", "Ặ", "Â", "Ấ", "Ầ", "Ẩ", "Ẫ", "Ậ", "Å", 114 | "Ā", "Ą", "Α", "Ά", "Ἀ", "Ἁ", "Ἂ", "Ἃ", "Ἄ", "Ἅ", "Ἆ", "Ἇ", "ᾈ", "ᾉ", "ᾊ", "ᾋ", "ᾌ", "ᾍ", 115 | "ᾎ", "ᾏ", "Ᾰ", "Ᾱ", "Ὰ", "Ά", "ᾼ", "А", "Ǻ", "Ǎ")); 116 | put("B", Arrays.asList("Б", "Β", "ब")); 117 | put("C", Arrays.asList("Ç", "Ć", "Č", "Ĉ", "Ċ")); 118 | put("D", Arrays.asList("Ď", "Ð", "Đ", "Ɖ", "Ɗ", "Ƌ", "ᴅ", "ᴆ", "Д", "Δ")); 119 | put("E", Arrays.asList("É", "È", "Ẻ", "Ẽ", "Ẹ", "Ê", "Ế", "Ề", "Ể", "Ễ", "Ệ", "Ë", "Ē", "Ę", "Ě", "Ĕ", "Ė", "Ε", 120 | "Έ", "Ἐ", "Ἑ", "Ἒ", "Ἓ", "Ἔ", "Ἕ", "Έ", "Ὲ", "Е", "Ё", "Э", "Є", "Ə")); 121 | put("F", Arrays.asList("Ф", "Φ")); 122 | put("G", Arrays.asList("Ğ", "Ġ", "Ģ", "Г", "Ґ", "Γ")); 123 | put("H", Arrays.asList("Η", "Ή", "Ħ")); 124 | put("I", Arrays.asList("Í", "Ì", "Ỉ", "Ĩ", "Ị", "Î", "Ï", "Ī", "Ĭ", "Į", "İ", "Ι", "Ί", "Ϊ", "Ἰ", "Ἱ", "Ἳ", "Ἴ", 125 | "Ἵ", "Ἶ", "Ἷ", "Ῐ", "Ῑ", "Ὶ", "Ί", "И", "І", "Ї", "Ǐ", "ϒ")); 126 | put("K", Arrays.asList("К", "Κ")); 127 | put("L", Arrays.asList("Ĺ", "Ł", "Л", "Λ", "Ļ", "Ľ", "Ŀ", "ल")); 128 | put("M", Arrays.asList("М", "Μ")); 129 | put("N", Arrays.asList("Ń", "Ñ", "Ň", "Ņ", "Ŋ", "Н", "Ν")); 130 | put("O", Arrays.asList("Ó", "Ò", "Ỏ", "Õ", "Ọ", "Ô", "Ố", "Ồ", "Ổ", "Ỗ", "Ộ", "Ơ", "Ớ", "Ờ", "Ở", "Ỡ", "Ợ", "Ø", 131 | "Ō", "Ő", "Ŏ", "Ο", "Ό", "Ὀ", "Ὁ", "Ὂ", "Ὃ", "Ὄ", "Ὅ", "Ὸ", "Ό", "О", "Θ", "Ө", "Ǒ", "Ǿ")); 132 | put("P", Arrays.asList("П", "Π")); 133 | put("R", Arrays.asList("Ř", "Ŕ", "Р", "Ρ", "Ŗ")); 134 | put("S", Arrays.asList("Ş", "Ŝ", "Ș", "Š", "Ś", "С", "Σ")); 135 | put("T", Arrays.asList("Ť", "Ţ", "Ŧ", "Ț", "Т", "Τ")); 136 | put("U", Arrays.asList("Ú", "Ù", "Ủ", "Ũ", "Ụ", "Ư", "Ứ", "Ừ", "Ử", "Ữ", "Ự", "Û", "Ū", "Ů", "Ű", "Ŭ", "Ų", "У", 137 | "Ǔ", "Ǖ", "Ǘ", "Ǚ", "Ǜ")); 138 | put("V", Arrays.asList("В")); 139 | put("W", Arrays.asList("Ω", "Ώ", "Ŵ")); 140 | put("X", Arrays.asList("Χ", "Ξ")); 141 | put("Y", Arrays.asList("Ý", "Ỳ", "Ỷ", "Ỹ", "Ỵ", "Ÿ", "Ῠ", "Ῡ", "Ὺ", "Ύ", "Ы", "Й", "Υ", "Ϋ", "Ŷ")); 142 | put("Z", Arrays.asList("Ź", "Ž", "Ż", "З", "Ζ")); 143 | put("AE", Arrays.asList("Ä", "Æ", "Ǽ")); 144 | put("CH", Arrays.asList("Ч")); 145 | put("DJ", Arrays.asList("Ђ")); 146 | put("DZ", Arrays.asList("Џ")); 147 | put("GX", Arrays.asList("Ĝ")); 148 | put("HX", Arrays.asList("Ĥ")); 149 | put("IJ", Arrays.asList("IJ")); 150 | put("JX", Arrays.asList("Ĵ")); 151 | put("KH", Arrays.asList("Х")); 152 | put("LJ", Arrays.asList("Љ")); 153 | put("NJ", Arrays.asList("Њ")); 154 | put("OE", Arrays.asList("Ö", "Œ")); 155 | put("PS", Arrays.asList("Ψ")); 156 | put("SH", Arrays.asList("Ш")); 157 | put("SHCH", Arrays.asList("Щ")); 158 | put("SS", Arrays.asList("ẞ")); 159 | put("TH", Arrays.asList("Þ")); 160 | put("TS", Arrays.asList("Ц")); 161 | put("UE", Arrays.asList("Ü")); 162 | put("YA", Arrays.asList("Я")); 163 | put("YU", Arrays.asList("Ю")); 164 | put("ZH", Arrays.asList("Ж")); 165 | put(" ", Arrays.asList("\\xC2\\xA0", "\\xE2\\x80\\x80", "\\xE2\\x80\\x81", "\\xE2\\x80\\x82", "\\xE2\\x80\\x83", 166 | "\\xE2\\x80\\x84", "\\xE2\\x80\\x85", "\\xE2\\x80\\x86", "\\xE2\\x80\\x87", "\\xE2\\x80\\x88", 167 | "\\xE2\\x80\\x89", "\\xE2\\x80\\x8A", "\\xE2\\x80\\xAF", "\\xE2\\x81\\x9F", "\\xE3\\x80\\x80")); 168 | 169 | 170 | }}; 171 | 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/strman/Strman.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * The MIT License 4 | * * 5 | * * Copyright 2016 Shekhar Gulati . 6 | * * 7 | * * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * * of this software and associated documentation files (the "Software"), to deal 9 | * * in the Software without restriction, including without limitation the rights 10 | * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * * copies of the Software, and to permit persons to whom the Software is 12 | * * furnished to do so, subject to the following conditions: 13 | * * 14 | * * The above copyright notice and this permission notice shall be included in 15 | * * all copies or substantial portions of the Software. 16 | * * 17 | * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | package strman; 28 | 29 | import java.nio.charset.StandardCharsets; 30 | import java.util.*; 31 | import java.util.function.Predicate; 32 | import java.util.function.Supplier; 33 | import java.util.regex.Matcher; 34 | import java.util.regex.Pattern; 35 | import java.util.stream.IntStream; 36 | import java.util.stream.Stream; 37 | 38 | import static java.util.function.Function.identity; 39 | import static java.util.stream.Collectors.*; 40 | 41 | /** 42 | * A String manipulation library without any dependencies 43 | */ 44 | public abstract class Strman { 45 | 46 | private static final Predicate NULL_STRING_PREDICATE = Objects::isNull; 47 | private static final Supplier NULL_STRING_MSG_SUPPLIER = () -> "'value' should be not null."; 48 | private static final String[] EMPTY_ARRAY = new String[0]; 49 | 50 | private Strman() { 51 | } 52 | 53 | /** 54 | * Appends Strings to value 55 | * 56 | * @param value initial String 57 | * @param appends an array of strings to append 58 | * @return full String 59 | */ 60 | public static String append(final String value, final String... appends) { 61 | return appendArray(value, appends); 62 | } 63 | 64 | /** 65 | * Append an array of String to value 66 | * 67 | * @param value initial String 68 | * @param appends an array of strings to append 69 | * @return full String 70 | */ 71 | public static String appendArray(final String value, final String[] appends) { 72 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 73 | if (appends == null || appends.length == 0) { 74 | return value; 75 | } 76 | StringJoiner joiner = new StringJoiner(""); 77 | for (String append : appends) { 78 | joiner.add(append); 79 | } 80 | return value + joiner.toString(); 81 | } 82 | 83 | /** 84 | * Get the character at index. This method will take care of negative indexes. 85 | * The valid value of index is between -(length-1) to (length-1). 86 | * For values which don't fall under this range Optional.empty will be returned. 87 | * 88 | * @param value input value 89 | * @param index location 90 | * @return an Optional String if found else empty 91 | */ 92 | public static Optional at(final String value, int index) { 93 | if (isNullOrEmpty(value)) { 94 | return Optional.empty(); 95 | } 96 | int length = value.length(); 97 | if (index < 0) { 98 | index = length + index; 99 | } 100 | return (index < length && index >= 0) ? Optional.of(String.valueOf(value.charAt(index))) : Optional.empty(); 101 | } 102 | 103 | /** 104 | * Returns an array with strings between start and end. 105 | * 106 | * @param value input 107 | * @param start start 108 | * @param end end 109 | * @return Array containing different parts between start and end. 110 | */ 111 | 112 | public static String[] between(final String value, final String start, final String end) { 113 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 114 | validate(start, NULL_STRING_PREDICATE, () -> "'start' should be not null."); 115 | validate(end, NULL_STRING_PREDICATE, () -> "'end' should be not null."); 116 | 117 | String[] parts = value.split(end); 118 | return Arrays.stream(parts) 119 | .filter(subPart -> subPart.contains(start)) 120 | .map(subPart -> subPart.substring(subPart.indexOf(start) + start.length())) 121 | .toArray(String[]::new); 122 | } 123 | 124 | /** 125 | * Returns a String array consisting of the characters in the String. 126 | * 127 | * @param value input 128 | * @return character array 129 | */ 130 | public static String[] chars(final String value) { 131 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 132 | return value.split(""); 133 | } 134 | 135 | /** 136 | * Replace consecutive whitespace characters with a single space. 137 | * 138 | * @param value input String 139 | * @return collapsed String 140 | */ 141 | public static String collapseWhitespace(final String value) { 142 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 143 | return value.trim().replaceAll("\\s\\s+", " "); 144 | } 145 | 146 | /** 147 | * Verifies that the needle is contained in the value. The search is case insensitive 148 | * 149 | * @param value to search 150 | * @param needle to find 151 | * @return true if found else false. 152 | */ 153 | public static boolean contains(final String value, final String needle) { 154 | return contains(value, needle, false); 155 | } 156 | 157 | /** 158 | * Verifies that the needle is contained in the value. 159 | * 160 | * @param value to search 161 | * @param needle to find 162 | * @param caseSensitive true or false 163 | * @return true if found else false. 164 | */ 165 | public static boolean contains(final String value, final String needle, final boolean caseSensitive) { 166 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 167 | if (caseSensitive) { 168 | return value.contains(needle); 169 | } 170 | return value.toLowerCase().contains(needle.toLowerCase()); 171 | } 172 | 173 | /** 174 | * Verifies that all needles are contained in value. The search is case insensitive 175 | * 176 | * @param value input String to search 177 | * @param needles needles to find 178 | * @return true if all needles are found else false. 179 | */ 180 | public static boolean containsAll(final String value, final String[] needles) { 181 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 182 | return Arrays.stream(needles).allMatch(needle -> contains(value, needle, false)); 183 | } 184 | 185 | /** 186 | * Verifies that all needles are contained in value 187 | * 188 | * @param value input String to search 189 | * @param needles needles to find 190 | * @param caseSensitive true or false 191 | * @return true if all needles are found else false. 192 | */ 193 | public static boolean containsAll(final String value, final String[] needles, final boolean caseSensitive) { 194 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 195 | return Arrays.stream(needles).allMatch(needle -> contains(value, needle, caseSensitive)); 196 | } 197 | 198 | /** 199 | * Verifies that one or more of needles are contained in value. This is case insensitive 200 | * 201 | * @param value input 202 | * @param needles needles to search 203 | * @return boolean true if any needle is found else false 204 | */ 205 | public static boolean containsAny(final String value, final String[] needles) { 206 | return containsAny(value, needles, false); 207 | } 208 | 209 | /** 210 | * Verifies that one or more of needles are contained in value. 211 | * 212 | * @param value input 213 | * @param needles needles to search 214 | * @param caseSensitive true or false 215 | * @return boolean true if any needle is found else false 216 | */ 217 | public static boolean containsAny(final String value, final String[] needles, final boolean caseSensitive) { 218 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 219 | return Arrays.stream(needles).anyMatch(needle -> contains(value, needle, caseSensitive)); 220 | } 221 | 222 | /** 223 | * Count the number of times substr appears in value 224 | * 225 | * @param value input 226 | * @param subStr to search 227 | * @return count of times substring exists 228 | */ 229 | public static long countSubstr(final String value, final String subStr) { 230 | return countSubstr(value, subStr, true, false); 231 | } 232 | 233 | /** 234 | * Count the number of times substr appears in value 235 | * 236 | * @param value input 237 | * @param subStr search string 238 | * @param caseSensitive whether search should be case sensitive 239 | * @param allowOverlapping boolean to take into account overlapping 240 | * @return count of times substring exists 241 | */ 242 | public static long countSubstr(final String value, final String subStr, final boolean caseSensitive, 243 | boolean allowOverlapping) { 244 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 245 | return countSubstr(caseSensitive ? value : value.toLowerCase(), caseSensitive ? subStr : subStr.toLowerCase(), 246 | allowOverlapping, 0L); 247 | } 248 | 249 | /** 250 | * Test if value ends with search. The search is case sensitive. 251 | * 252 | * @param value input string 253 | * @param search string to search 254 | * @return true or false 255 | */ 256 | public static boolean endsWith(final String value, final String search) { 257 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 258 | return endsWith(value, search, value.length(), true); 259 | } 260 | 261 | /** 262 | * Test if value ends with search. 263 | * 264 | * @param value input string 265 | * @param search string to search 266 | * @param caseSensitive true or false 267 | * @return true or false 268 | */ 269 | public static boolean endsWith(final String value, final String search, final boolean caseSensitive) { 270 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 271 | return endsWith(value, search, value.length(), caseSensitive); 272 | } 273 | 274 | /** 275 | * Test if value ends with search. 276 | * 277 | * @param value input string 278 | * @param search string to search 279 | * @param position position till which you want to search. 280 | * @param caseSensitive true or false 281 | * @return true or false 282 | */ 283 | public static boolean endsWith(final String value, final String search, final int position, 284 | final boolean caseSensitive) { 285 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 286 | int remainingLength = position - search.length(); 287 | if (caseSensitive) { 288 | return value.indexOf(search, remainingLength) > -1; 289 | } 290 | return value.toLowerCase().indexOf(search.toLowerCase(), remainingLength) > -1; 291 | } 292 | 293 | /** 294 | * Ensures that the value begins with prefix. If it doesn't exist, it's prepended. It is case sensitive. 295 | * 296 | * @param value input 297 | * @param prefix prefix 298 | * @return string with prefix if it was not present. 299 | */ 300 | public static String ensureLeft(final String value, final String prefix) { 301 | return ensureLeft(value, prefix, true); 302 | } 303 | 304 | /** 305 | * Ensures that the value begins with prefix. If it doesn't exist, it's prepended. 306 | * 307 | * @param value input 308 | * @param prefix prefix 309 | * @param caseSensitive true or false 310 | * @return string with prefix if it was not present. 311 | */ 312 | public static String ensureLeft(final String value, final String prefix, final boolean caseSensitive) { 313 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 314 | if (caseSensitive) { 315 | return value.startsWith(prefix) ? value : prefix + value; 316 | } 317 | String _value = value.toLowerCase(); 318 | String _prefix = prefix.toLowerCase(); 319 | return _value.startsWith(_prefix) ? value : prefix + value; 320 | } 321 | 322 | /** 323 | * Decodes data encoded with MIME base64 324 | * 325 | * @param value The data to decode 326 | * @return decoded data 327 | */ 328 | public static String base64Decode(final String value) { 329 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 330 | return new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8); 331 | } 332 | 333 | /** 334 | * Encodes data with MIME base64. 335 | * 336 | * @param value The data to encode 337 | * @return The encoded String 338 | */ 339 | public static String base64Encode(final String value) { 340 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 341 | return Base64.getEncoder().encodeToString(value.getBytes(StandardCharsets.UTF_8)); 342 | } 343 | 344 | /** 345 | * Convert binary unicode (16 digits) string to string chars 346 | * 347 | * @param value The value to decode 348 | * @return The decoded String 349 | */ 350 | public static String binDecode(final String value) { 351 | return decode(value, 16, 2); 352 | } 353 | 354 | /** 355 | * Convert string chars to binary unicode (16 digits) 356 | * 357 | * @param value The value to encode 358 | * @return String in binary format 359 | */ 360 | public static String binEncode(final String value) { 361 | return encode(value, 16, 2); 362 | } 363 | 364 | /** 365 | * Convert decimal unicode (5 digits) string to string chars 366 | * 367 | * @param value The value to decode 368 | * @return decoded String 369 | */ 370 | public static String decDecode(final String value) { 371 | return decode(value, 5, 10); 372 | } 373 | 374 | /** 375 | * Convert string chars to decimal unicode (5 digits) 376 | * 377 | * @param value The value to encode 378 | * @return Encoded value 379 | */ 380 | public static String decEncode(final String value) { 381 | return encode(value, 5, 10); 382 | } 383 | 384 | /** 385 | * Ensures that the value ends with suffix. If it doesn't, it's appended. This operation is case sensitive. 386 | * 387 | * @param value The input String 388 | * @param suffix The substr to be ensured to be right 389 | * @return The string which is guarenteed to start with substr 390 | */ 391 | public static String ensureRight(final String value, final String suffix) { 392 | return ensureRight(value, suffix, true); 393 | } 394 | 395 | /** 396 | * Ensures that the value ends with suffix. If it doesn't, it's appended. 397 | * 398 | * @param value The input String 399 | * @param suffix The substr to be ensured to be right 400 | * @param caseSensitive Use case (in-)sensitive matching for determining if value already ends with suffix 401 | * @return The string which is guarenteed to start with substr 402 | */ 403 | public static String ensureRight(final String value, final String suffix, boolean caseSensitive) { 404 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 405 | return endsWith(value, suffix, caseSensitive) ? value : append(value, suffix); 406 | } 407 | 408 | /** 409 | * Returns the first n chars of String 410 | * 411 | * @param value The input String 412 | * @param n Number of chars to return 413 | * @return The first n chars 414 | */ 415 | public static Optional first(final String value, final int n) { 416 | return Optional.ofNullable(value).filter(v -> !v.isEmpty()).map(v -> v.substring(0, n)); 417 | } 418 | 419 | /** 420 | * Return the first char of String 421 | * 422 | * @param value The input String 423 | * @return The first char 424 | */ 425 | public static Optional head(final String value) { 426 | return first(value, 1); 427 | } 428 | 429 | /** 430 | * Formats a string using parameters 431 | * 432 | * @param value The value to be formatted 433 | * @param params Parameters to be described in the string 434 | * @return The formatted string 435 | */ 436 | public static String format(final String value, String... params) { 437 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 438 | Pattern p = Pattern.compile("\\{(\\w+)}"); 439 | Matcher m = p.matcher(value); 440 | String result = value; 441 | while (m.find()) { 442 | int paramNumber = Integer.parseInt(m.group(1)); 443 | if (params == null || paramNumber >= params.length) { 444 | throw new IllegalArgumentException("params does not have value for " + m.group()); 445 | } 446 | result = result.replace(m.group(), params[paramNumber]); 447 | } 448 | return result; 449 | } 450 | 451 | /** 452 | * Convert hexadecimal unicode (4 digits) string to string chars 453 | * 454 | * @param value The value to decode 455 | * @return The decoded String 456 | */ 457 | public static String hexDecode(final String value) { 458 | return decode(value, 4, 16); 459 | } 460 | 461 | /** 462 | * Convert string chars to hexadecimal unicode (4 digits) 463 | * 464 | * @param value The value to encode 465 | * @return String in hexadecimal format. 466 | */ 467 | public static String hexEncode(final String value) { 468 | return encode(value, 4, 16); 469 | } 470 | 471 | /** 472 | * The indexOf() method returns the index within the calling String of the first occurrence of the specified value, starting the search at fromIndex. 473 | * Returns -1 if the value is not found. 474 | * 475 | * @param value The input String 476 | * @param needle The search String 477 | * @param offset The offset to start searching from. 478 | * @param caseSensitive boolean to indicate whether search should be case sensitive 479 | * @return Returns position of first occurrence of needle. 480 | */ 481 | public static int indexOf(final String value, final String needle, int offset, boolean caseSensitive) { 482 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 483 | if (caseSensitive) { 484 | return value.indexOf(needle, offset); 485 | } 486 | return value.toLowerCase().indexOf(needle.toLowerCase(), offset); 487 | } 488 | 489 | /** 490 | * Tests if two Strings are inequal 491 | * 492 | * @param first The first String 493 | * @param second The second String 494 | * @return true if first and second are not equal false otherwise 495 | */ 496 | public static boolean unequal(final String first, final String second) { 497 | return !Objects.equals(first, second); 498 | } 499 | 500 | /** 501 | * Tests if two Strings are inequal 502 | * 503 | * @param first The first String 504 | * @param second The second String 505 | * @return true if first and second are not equal false otherwise 506 | * @deprecated use unequal instead 507 | */ 508 | public static boolean inequal(final String first, final String second) { 509 | return !Objects.equals(first, second); 510 | } 511 | 512 | /** 513 | * Inserts 'substr' into the 'value' at the 'index' provided. 514 | * 515 | * @param value The input String 516 | * @param substr The String to insert 517 | * @param index The index to insert substr 518 | * @return String with substr added 519 | */ 520 | public static String insert(final String value, final String substr, final int index) { 521 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 522 | validate(substr, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 523 | if (index > value.length()) { 524 | return value; 525 | } 526 | return append(value.substring(0, index), substr, value.substring(index)); 527 | } 528 | 529 | /** 530 | * Verifies if String is uppercase 531 | * 532 | * @param value The input String 533 | * @return true if String is uppercase false otherwise 534 | */ 535 | public static boolean isUpperCase(final String value) { 536 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 537 | for (int i = 0; i < value.length(); i++) { 538 | if (Character.isLowerCase(value.charAt(i))) { 539 | return false; 540 | } 541 | } 542 | return true; 543 | } 544 | 545 | /** 546 | * Verifies if String is lower case 547 | * 548 | * @param value The input String 549 | * @return true if String is lowercase false otherwise 550 | */ 551 | public static boolean isLowerCase(final String value) { 552 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 553 | for (int i = 0; i < value.length(); i++) { 554 | if (Character.isUpperCase(value.charAt(i))) { 555 | return false; 556 | } 557 | } 558 | return true; 559 | } 560 | 561 | /** 562 | * Return the last n chars of String 563 | * 564 | * @param value The input String 565 | * @param n Number of chars to return 566 | * @return n Last characters 567 | */ 568 | public static String last(final String value, int n) { 569 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 570 | if (n > value.length()) { 571 | return value; 572 | } 573 | return value.substring(value.length() - n); 574 | } 575 | 576 | /** 577 | * Returns a new string of a given length such that the beginning of the string is padded. 578 | * 579 | * @param value The input String 580 | * @param pad The pad 581 | * @param length Length of the String we want 582 | * @return Padded String 583 | */ 584 | public static String leftPad(final String value, final String pad, final int length) { 585 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 586 | validate(pad, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 587 | if (value.length() > length) { 588 | return value; 589 | } 590 | return append(repeat(pad, length - value.length()), value); 591 | } 592 | 593 | /** 594 | * Checks whether Object is String 595 | * 596 | * @param value The input String 597 | * @return true if Object is a String false otherwise 598 | */ 599 | public static boolean isString(final Object value) { 600 | if (Objects.isNull(value)) { 601 | throw new IllegalArgumentException("value can't be null"); 602 | } 603 | return value instanceof String; 604 | } 605 | 606 | /** 607 | * This method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from the offset. 608 | * Returns -1 if the value is not found. The search starts from the end and case sensitive. 609 | * 610 | * @param value The input String 611 | * @param needle The search String 612 | * @return Return position of the last occurrence of 'needle'. 613 | */ 614 | public static int lastIndexOf(final String value, final String needle) { 615 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 616 | return lastIndexOf(value, needle, value.length(), true); 617 | } 618 | 619 | /** 620 | * This method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from the offset. 621 | * Returns -1 if the value is not found. The search starts from the end and case sensitive. 622 | * 623 | * @param value The input String 624 | * @param needle The search String 625 | * @param caseSensitive true or false 626 | * @return Return position of the last occurrence of 'needle'. 627 | */ 628 | public static int lastIndexOf(final String value, final String needle, boolean caseSensitive) { 629 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 630 | return lastIndexOf(value, needle, value.length(), caseSensitive); 631 | } 632 | 633 | /** 634 | * This method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from the offset. 635 | * Returns -1 if the value is not found. 636 | * 637 | * @param value The input String 638 | * @param needle The search String 639 | * @param offset The index to start search from 640 | * @param caseSensitive whether search should be case sensitive 641 | * @return Return position of the last occurrence of 'needle'. 642 | */ 643 | public static int lastIndexOf(final String value, final String needle, final int offset, 644 | final boolean caseSensitive) { 645 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 646 | validate(needle, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 647 | if (caseSensitive) { 648 | return value.lastIndexOf(needle, offset); 649 | } 650 | return value.toLowerCase().lastIndexOf(needle.toLowerCase(), offset); 651 | } 652 | 653 | /** 654 | * Removes all spaces on left 655 | * 656 | * @param value The input String 657 | * @return String without left border spaces 658 | */ 659 | public static String leftTrim(final String value) { 660 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 661 | return value.replaceAll("^\\s+", ""); 662 | } 663 | 664 | /** 665 | * Returns length of String. Delegates to java.lang.String length method. 666 | * 667 | * @param value The input String 668 | * @return Length of the String 669 | */ 670 | public static int length(final String value) { 671 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 672 | return value.length(); 673 | } 674 | 675 | /** 676 | * Return a new String starting with prepends 677 | * 678 | * @param value The input String 679 | * @param prepends Strings to prepend 680 | * @return The prepended String 681 | */ 682 | public static String prepend(final String value, final String... prepends) { 683 | return prependArray(value, prepends); 684 | } 685 | 686 | /** 687 | * Return a new String starting with prepends 688 | * 689 | * @param value The input String 690 | * @param prepends Strings to prepend 691 | * @return The prepended String 692 | */ 693 | public static String prependArray(final String value, final String[] prepends) { 694 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 695 | if (prepends == null || prepends.length == 0) { 696 | return value; 697 | } 698 | StringJoiner joiner = new StringJoiner(""); 699 | for (String prepend : prepends) { 700 | joiner.add(prepend); 701 | } 702 | return joiner.toString() + value; 703 | } 704 | 705 | /** 706 | * Remove empty Strings from string array 707 | * 708 | * @param strings Array of String to be cleaned 709 | * @return Array of String without empty Strings 710 | */ 711 | public static String[] removeEmptyStrings(String[] strings) { 712 | if (Objects.isNull(strings)) { 713 | throw new IllegalArgumentException("Input array should not be null"); 714 | } 715 | return Arrays.stream(strings).filter(str -> str != null && !str.trim().isEmpty()).toArray(String[]::new); 716 | } 717 | 718 | /** 719 | * Returns a new String with the prefix removed, if present. This is case sensitive. 720 | * 721 | * @param value The input String 722 | * @param prefix String to remove on left 723 | * @return The String without prefix 724 | */ 725 | public static String removeLeft(final String value, final String prefix) { 726 | return removeLeft(value, prefix, true); 727 | } 728 | 729 | /** 730 | * Returns a new String with the prefix removed, if present. 731 | * 732 | * @param value The input String 733 | * @param prefix String to remove on left 734 | * @param caseSensitive ensure case sensitivity 735 | * @return The String without prefix 736 | */ 737 | public static String removeLeft(final String value, final String prefix, final boolean caseSensitive) { 738 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 739 | validate(prefix, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 740 | if (caseSensitive) { 741 | return value.startsWith(prefix) ? value.substring(prefix.length()) : value; 742 | } 743 | return value.toLowerCase().startsWith(prefix.toLowerCase()) ? value.substring(prefix.length()) : value; 744 | } 745 | 746 | /** 747 | * Remove all non word characters. 748 | * 749 | * @param value The input String 750 | * @return String without non-word characters 751 | */ 752 | public static String removeNonWords(final String value) { 753 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 754 | return value.replaceAll("[^\\w]+", ""); 755 | } 756 | 757 | /** 758 | * Returns a new string with the 'suffix' removed, if present. Search is case sensitive. 759 | * 760 | * @param value The input String 761 | * @param suffix The suffix to remove 762 | * @return The String without suffix! 763 | */ 764 | public static String removeRight(final String value, final String suffix) { 765 | return removeRight(value, suffix, true); 766 | } 767 | 768 | /** 769 | * Returns a new string with the 'suffix' removed, if present. 770 | * 771 | * @param value The input String 772 | * @param suffix The suffix to remove 773 | * @param caseSensitive whether search should be case sensitive or not 774 | * @return The String without suffix! 775 | */ 776 | public static String removeRight(final String value, final String suffix, final boolean caseSensitive) { 777 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 778 | validate(suffix, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 779 | return endsWith(value, suffix, caseSensitive) ? value 780 | .substring(0, value.toLowerCase().lastIndexOf(suffix.toLowerCase())) : value; 781 | } 782 | 783 | /** 784 | * Remove all spaces and replace for value. 785 | * 786 | * @param value The input String 787 | * @return String without spaces 788 | */ 789 | public static String removeSpaces(final String value) { 790 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 791 | return value.replaceAll("\\s", ""); 792 | } 793 | 794 | /** 795 | * Returns a repeated string given a multiplier. 796 | * 797 | * @param value The input String 798 | * @param multiplier Number of repeats 799 | * @return The String repeated 800 | */ 801 | public static String repeat(final String value, final int multiplier) { 802 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 803 | return Stream.generate(() -> value).limit(multiplier).collect(joining()); 804 | } 805 | 806 | /** 807 | * Replace all occurrences of 'search' value to 'newvalue'. Uses String replace method. 808 | * 809 | * @param value The input 810 | * @param search The String to search 811 | * @param newValue The String to replace 812 | * @param caseSensitive whether search should be case sensitive or not 813 | * @return String replaced with 'newvalue'. 814 | */ 815 | public static String replace(final String value, final String search, final String newValue, 816 | final boolean caseSensitive) { 817 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 818 | validate(search, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 819 | if (caseSensitive) { 820 | return value.replace(search, newValue); 821 | } 822 | return Pattern.compile(search, Pattern.CASE_INSENSITIVE).matcher(value) 823 | .replaceAll(Matcher.quoteReplacement(newValue)); 824 | } 825 | 826 | /** 827 | * Reverse the input String 828 | * 829 | * @param value The input String 830 | * @return Reversed String 831 | */ 832 | public static String reverse(final String value) { 833 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 834 | return new StringBuilder(value).reverse().toString(); 835 | } 836 | 837 | /** 838 | * Returns a new string of a given length such that the ending of the string is padded. 839 | * 840 | * @param value The input String 841 | * @param length Max length of String. 842 | * @param pad Character to repeat 843 | * @return Right padded String 844 | */ 845 | public static String rightPad(final String value, String pad, final int length) { 846 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 847 | if (value.length() > length) { 848 | return value; 849 | } 850 | return append(value, repeat(pad, length - value.length())); 851 | } 852 | 853 | /** 854 | * Remove all spaces on right. 855 | * 856 | * @param value The String 857 | * @return String without right boarders spaces. 858 | */ 859 | public static String rightTrim(final String value) { 860 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 861 | return value.replaceAll("\\s+$", ""); 862 | } 863 | 864 | /** 865 | * Truncate the string securely, not cutting a word in half. It always returns the last full word. 866 | * 867 | * @param value The input String 868 | * @param length Max size of the truncated String 869 | * @param filler String that will be added to the end of the return string. Example: '...' 870 | * @return The truncated String 871 | */ 872 | public static String safeTruncate(final String value, final int length, final String filler) { 873 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 874 | if (length == 0) { 875 | return ""; 876 | } 877 | if (length >= value.length()) { 878 | return value; 879 | } 880 | 881 | String[] words = words(value); 882 | StringJoiner result = new StringJoiner(" "); 883 | int spaceCount = 0; 884 | for (String word : words) { 885 | if (result.length() + word.length() + filler.length() + spaceCount > length) { 886 | break; 887 | } else { 888 | result.add(word); 889 | spaceCount++; 890 | } 891 | } 892 | return append(result.toString(), filler); 893 | } 894 | 895 | /** 896 | * Alias to String split function. Defined only for completeness. 897 | * 898 | * @param value The input String 899 | * @param regex The delimiting regular expression 900 | * @return String Array 901 | */ 902 | public static String[] split(final String value, final String regex) { 903 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 904 | return value.split(regex); 905 | } 906 | 907 | /** 908 | * Splits a String to words 909 | * 910 | * @param value The input String 911 | * @return Words Array 912 | */ 913 | public static String[] words(final String value) { 914 | return words(value, "\\s+"); 915 | } 916 | 917 | /** 918 | * Splits a String to words by delimiter, \s+ by default 919 | * 920 | * @param value The input String 921 | * @param delimiter delimiter for splitting input String 922 | * @return words array 923 | */ 924 | public static String[] words(final String value, final String delimiter) { 925 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 926 | return value.split(delimiter); 927 | } 928 | 929 | 930 | /** 931 | * Truncate the unsecured form string, cutting the independent string of required position. 932 | * 933 | * @param value Value will be truncated unsecurely. 934 | * @param length Size of the returned string. 935 | * @param filler Value that will be added to the end of the return string. Example: '...' 936 | * @return String truncated unsafely. 937 | */ 938 | public static String truncate(final String value, final int length, final String filler) { 939 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 940 | if (length == 0) { 941 | return ""; 942 | } 943 | if (length >= value.length()) { 944 | return value; 945 | } 946 | return append(value.substring(0, length - filler.length()), filler); 947 | } 948 | 949 | /** 950 | * Converts all HTML entities to applicable characters. 951 | * 952 | * @param encodedHtml The encoded HTML 953 | * @return The decoded HTML 954 | */ 955 | public static String htmlDecode(final String encodedHtml) { 956 | validate(encodedHtml, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 957 | String[] entities = encodedHtml.split("&\\W+;"); 958 | return Arrays.stream(entities).map(e -> HtmlEntities.decodedEntities.get(e)).collect(joining()); 959 | } 960 | 961 | /** 962 | * Convert all applicable characters to HTML entities. 963 | * 964 | * @param html The HTML to encode 965 | * @return The encoded data 966 | */ 967 | public static String htmlEncode(final String html) { 968 | validate(html, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 969 | return html.chars().mapToObj(c -> "\\u" + String.format("%04x", c).toUpperCase()) 970 | .map(HtmlEntities.encodedEntities::get).collect(joining()); 971 | } 972 | 973 | /** 974 | * It returns a string with its characters in random order. 975 | * 976 | * @param value The input String 977 | * @return The shuffled String 978 | */ 979 | public static String shuffle(final String value) { 980 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 981 | String[] chars = chars(value); 982 | Random random = new Random(); 983 | for (int i = 0; i < chars.length; i++) { 984 | int r = random.nextInt(chars.length); 985 | String tmp = chars[i]; 986 | chars[i] = chars[r]; 987 | chars[r] = tmp; 988 | } 989 | return Arrays.stream(chars).collect(joining()); 990 | } 991 | 992 | /** 993 | * Alias of substring method 994 | * 995 | * @param value The input String 996 | * @param begin Start of slice. 997 | * @param end End of slice. 998 | * @return The String sliced! 999 | */ 1000 | public static String slice(final String value, int begin, int end) { 1001 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1002 | return value.substring(begin, end); 1003 | } 1004 | 1005 | /** 1006 | * Convert a String to a slug 1007 | * 1008 | * @param value The value to slugify 1009 | * @return The slugified value 1010 | */ 1011 | public static String slugify(final String value) { 1012 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1013 | String transliterated = transliterate(collapseWhitespace(value.trim().toLowerCase())); 1014 | return Arrays.stream(words(transliterated.replace("&", "-and-"), "\\W+")).collect(joining("-")); 1015 | } 1016 | 1017 | /** 1018 | * Remove all non valid characters. 1019 | * 1020 | * @param value The input String 1021 | * @return String without non valid characters. 1022 | */ 1023 | public static String transliterate(final String value) { 1024 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1025 | String result = value; 1026 | Set>> entries = Ascii.ascii.entrySet(); 1027 | for (Map.Entry> entry : entries) { 1028 | for (String ch : entry.getValue()) { 1029 | result = result.replace(ch, entry.getKey()); 1030 | } 1031 | } 1032 | return result; 1033 | } 1034 | 1035 | /** 1036 | * Surrounds a 'value' with the given 'prefix' and 'suffix'. 1037 | * 1038 | * @param value The input String 1039 | * @param prefix prefix. If suffix is null then prefix is used 1040 | * @param suffix suffix 1041 | * @return The String with surround substrs! 1042 | */ 1043 | public static String surround(final String value, final String prefix, final String suffix) { 1044 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1045 | String _prefix = Optional.ofNullable(prefix).orElse(""); 1046 | return append(_prefix, value, Optional.ofNullable(suffix).orElse(_prefix)); 1047 | } 1048 | 1049 | /** 1050 | * Transform to camelCase 1051 | * 1052 | * @param value The input String 1053 | * @return String in camelCase. 1054 | */ 1055 | public static String toCamelCase(final String value) { 1056 | if (value == null || value.length() == 0) { 1057 | return ""; 1058 | } 1059 | String str = toStudlyCase(value); 1060 | return str.substring(0, 1).toLowerCase() + str.substring(1); 1061 | } 1062 | 1063 | /** 1064 | * Transform to StudlyCaps. 1065 | * 1066 | * @param value The input String 1067 | * @return String in StudlyCaps. 1068 | */ 1069 | public static String toStudlyCase(final String value) { 1070 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1071 | String[] words = collapseWhitespace(value.trim()).split("\\s*(_|-|\\s)\\s*"); 1072 | return Arrays.stream(words).filter(w -> !w.trim().isEmpty()).map(Strman::upperFirst).collect(joining()); 1073 | } 1074 | 1075 | /** 1076 | * Return tail of the String 1077 | * 1078 | * @param value The input String 1079 | * @return String tail 1080 | */ 1081 | public static Optional tail(final String value) { 1082 | return Optional.ofNullable(value).filter(v -> !v.isEmpty()).map(v -> last(v, v.length() - 1)); 1083 | } 1084 | 1085 | /** 1086 | * Decamelize String 1087 | * 1088 | * @param value The input String 1089 | * @param chr string to use 1090 | * @return String decamelized. 1091 | */ 1092 | public static String toDecamelize(final String value, final String chr) { 1093 | String camelCasedString = toCamelCase(value); 1094 | String[] words = camelCasedString.split("(?=\\p{Upper})"); 1095 | return Arrays.stream(words).map(String::toLowerCase).collect(joining(Optional.ofNullable(chr).orElse(" "))); 1096 | } 1097 | 1098 | /** 1099 | * Transform to kebab-case. 1100 | * 1101 | * @param value The input String 1102 | * @return String in kebab-case. 1103 | */ 1104 | public static String toKebabCase(final String value) { 1105 | return toDecamelize(value, "-"); 1106 | } 1107 | 1108 | /** 1109 | * Transform to snake_case. 1110 | * 1111 | * @param value The input String 1112 | * @return String in snake_case. 1113 | */ 1114 | public static String toSnakeCase(final String value) { 1115 | return toDecamelize(value, "_"); 1116 | } 1117 | 1118 | public static String decode(final String value, final int digits, final int radix) { 1119 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1120 | return Arrays.stream(value.split("(?<=\\G.{" + digits + "})")) 1121 | .map(data -> String.valueOf(Character.toChars(Integer.parseInt(data, radix)))) 1122 | .collect(joining()); 1123 | } 1124 | 1125 | public static String encode(final String value, final int digits, final int radix) { 1126 | validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1127 | return value.chars().mapToObj(ch -> leftPad(Integer.toString(ch, radix), "0", digits)).collect(joining()); 1128 | } 1129 | 1130 | /** 1131 | * Join concatenates all the elements of the strings array into a single String. The separator string is placed between elements in the resulting string. 1132 | * 1133 | * @param strings The input array to concatenate 1134 | * @param separator The separator to use 1135 | * @return Concatenated String 1136 | */ 1137 | public static String join(final String[] strings, final String separator) throws IllegalArgumentException { 1138 | if (strings == null) { 1139 | throw new IllegalArgumentException("Input array 'strings' can't be null"); 1140 | } 1141 | if (separator == null) { 1142 | throw new IllegalArgumentException("separator can't be null"); 1143 | } 1144 | StringJoiner joiner = new StringJoiner(separator); 1145 | for (String el : strings) { 1146 | joiner.add(el); 1147 | } 1148 | return joiner.toString(); 1149 | } 1150 | 1151 | /** 1152 | * Converts the first character of string to upper case and the remaining to lower case. 1153 | * 1154 | * @param input The string to capitalize 1155 | * @return The capitalized string 1156 | */ 1157 | public static String capitalize(final String input) throws IllegalArgumentException { 1158 | if (input == null) { 1159 | throw new IllegalArgumentException("input can't be null"); 1160 | } 1161 | if (input.length() == 0) { 1162 | return ""; 1163 | } 1164 | return head(input).map(String::toUpperCase).map(h -> tail(input).map(t -> h + t.toLowerCase()).orElse(h)).get(); 1165 | } 1166 | 1167 | /** 1168 | * Converts the first character of string to lower case. 1169 | * 1170 | * @param input The string to convert 1171 | * @return The converted string 1172 | */ 1173 | public static String lowerFirst(final String input) throws IllegalArgumentException { 1174 | if (input == null) { 1175 | throw new IllegalArgumentException("input can't be null"); 1176 | } 1177 | if (input.length() == 0) { 1178 | return ""; 1179 | } 1180 | 1181 | return head(input).map(String::toLowerCase).map(h -> tail(input).map(t -> h + t).orElse(h)).get(); 1182 | } 1183 | 1184 | /** 1185 | * Verifies whether String is enclosed by encloser 1186 | * 1187 | * @param input The input String 1188 | * @param encloser String which encloses input String 1189 | * @return true if enclosed false otherwise 1190 | */ 1191 | public static boolean isEnclosedBetween(final String input, final String encloser) { 1192 | return isEnclosedBetween(input, encloser, encloser); 1193 | } 1194 | 1195 | /** 1196 | * Verifies whether String is enclosed by encloser 1197 | * 1198 | * @param input The input String 1199 | * @param leftEncloser String which encloses input String at left start 1200 | * @param rightEncloser String which encloses input String at the right end 1201 | * @return true if enclosed false otherwise 1202 | */ 1203 | public static boolean isEnclosedBetween(final String input, final String leftEncloser, String rightEncloser) { 1204 | if (input == null) { 1205 | throw new IllegalArgumentException("input can't be null"); 1206 | } 1207 | if (leftEncloser == null) { 1208 | throw new IllegalArgumentException("leftEncloser can't be null"); 1209 | } 1210 | if (rightEncloser == null) { 1211 | throw new IllegalArgumentException("rightEncloser can't be null"); 1212 | } 1213 | return input.startsWith(leftEncloser) && input.endsWith(rightEncloser); 1214 | } 1215 | 1216 | /** 1217 | * Converts the first character of string to upper case. 1218 | * 1219 | * @param input The string to convert. 1220 | * @return Returns the converted string. 1221 | */ 1222 | public static String upperFirst(String input) { 1223 | if (input == null) { 1224 | throw new IllegalArgumentException("input can't be null"); 1225 | } 1226 | return head(input).map(String::toUpperCase).map(h -> tail(input).map(t -> h + t).orElse(h)).get(); 1227 | } 1228 | 1229 | /** 1230 | * Removes leading whitespace from string. 1231 | * 1232 | * @param input The string to trim. 1233 | * @return Returns the trimmed string. 1234 | */ 1235 | public static Optional trimStart(final String input) { 1236 | return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(Strman::leftTrim); 1237 | } 1238 | 1239 | /** 1240 | * Removes leading characters from string. 1241 | * 1242 | * @param input The string to trim. 1243 | * @param chars The characters to trim. 1244 | * @return Returns the trimmed string. 1245 | */ 1246 | public static Optional trimStart(final String input, String... chars) { 1247 | return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(v -> { 1248 | String pattern = String.format("^[%s]+", join(chars, "\\")); 1249 | return v.replaceAll(pattern, ""); 1250 | }); 1251 | } 1252 | 1253 | /** 1254 | * Removes trailing whitespace from string. 1255 | * 1256 | * @param input The string to trim. 1257 | * @return Returns the trimmed string. 1258 | */ 1259 | public static Optional trimEnd(final String input) { 1260 | return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(Strman::rightTrim); 1261 | } 1262 | 1263 | /** 1264 | * Removes trailing characters from string. 1265 | * 1266 | * @param input The string to trim. 1267 | * @param chars The characters to trim. 1268 | * @return Returns the trimmed string. 1269 | */ 1270 | public static Optional trimEnd(final String input, String... chars) { 1271 | return Optional.ofNullable(input).filter(v -> !v.isEmpty()).map(v -> { 1272 | String pattern = String.format("[%s]+$", join(chars, "\\")); 1273 | return v.replaceAll(pattern, ""); 1274 | }); 1275 | } 1276 | 1277 | /** 1278 | * Counts the number of occurrences of each character in the string 1279 | * 1280 | * @param input The input string 1281 | * @return A map containing the number of occurrences of each character in the string 1282 | */ 1283 | public static Map charsCount(String input) { 1284 | if (isNullOrEmpty(input)) { 1285 | return Collections.emptyMap(); 1286 | } 1287 | 1288 | return input.chars().mapToObj(c -> (char) c).collect(groupingBy(identity(), counting())); 1289 | } 1290 | 1291 | /** 1292 | * Checks if string is empty. This is a null safe check and will return true when string is null. 1293 | * 1294 | * @param input The input string 1295 | * @return true if input string is null or empty 1296 | */ 1297 | public static boolean isBlank(String input) { 1298 | return input == null || input.isEmpty(); 1299 | } 1300 | 1301 | /** 1302 | * Changes passed in string to all lower case and adds underscore between words. 1303 | * 1304 | * @param input The input string 1305 | * @return the input string in all lower case with underscores between words 1306 | */ 1307 | public static String underscored(final String input) { 1308 | if (input == null || input.length() == 0) { 1309 | return ""; 1310 | } 1311 | 1312 | return input.trim().replaceAll("([a-z\\d])([A-Z]+)", "$1_$2").replaceAll("[-\\s]+", "_").toLowerCase(); 1313 | } 1314 | 1315 | /** 1316 | * Aggregates the contents of n strings into a single list of tuples. 1317 | * 1318 | * @param inputs A list of strings. 1319 | * @return A list of strings if none of the strings in the input is null or empty. 1320 | * An empty list otherwise. 1321 | */ 1322 | public static List zip(String... inputs) { 1323 | if (inputs.length == 0) { 1324 | return Collections.emptyList(); 1325 | } 1326 | OptionalInt min = Arrays.stream(inputs).mapToInt(str -> str == null ? 0 : str.length()).min(); 1327 | if (!min.isPresent()) { 1328 | return Collections.emptyList(); 1329 | } 1330 | return IntStream.range(0, min.getAsInt()) 1331 | .mapToObj(elementIndex -> Arrays.stream(inputs) 1332 | .map(input -> String.valueOf(input.charAt(elementIndex))) 1333 | .collect(joining())) 1334 | .collect(toList()); 1335 | } 1336 | 1337 | /** 1338 | * Split lines to an array 1339 | * 1340 | * @param input The input String 1341 | * @return lines in an array 1342 | */ 1343 | public static String[] lines(String input) { 1344 | if (input == null) { 1345 | return EMPTY_ARRAY; 1346 | } 1347 | return input.split("\r\n?|\n"); 1348 | } 1349 | 1350 | /** 1351 | * Converts a underscored or camelized string into an dasherized one. 1352 | * 1353 | * @param input The input String 1354 | * @return dasherized String. 1355 | */ 1356 | public static String dasherize(String input) { 1357 | return toKebabCase(input); 1358 | } 1359 | 1360 | /** 1361 | * Converts an underscored, camelized, or dasherized string into a humanized one. Also removes beginning and ending whitespace. 1362 | * 1363 | * @param input The input String 1364 | * @return humanized version of String 1365 | */ 1366 | public static String humanize(final String input) { 1367 | if (input == null || input.length() == 0) { 1368 | return ""; 1369 | } 1370 | return upperFirst(underscored(input).replaceAll("_", " ")); 1371 | } 1372 | 1373 | /** 1374 | * Returns a copy of the string in which all the case-based characters have had their case swapped. 1375 | * 1376 | * @param input Input string 1377 | * @return String with all the case swapped 1378 | */ 1379 | public static String swapCase(String input) { 1380 | if (input == null || input.length() == 0) { 1381 | return ""; 1382 | } 1383 | StringBuilder resultBuilder = new StringBuilder(); 1384 | for (char ch : input.toCharArray()) { 1385 | if (Character.isUpperCase(ch)) { 1386 | resultBuilder.append(Character.toLowerCase(ch)); 1387 | } else { 1388 | resultBuilder.append(Character.toUpperCase(ch)); 1389 | } 1390 | } 1391 | return resultBuilder.toString(); 1392 | } 1393 | 1394 | /** 1395 | * Returns a string representation of the number passed in where groups of three digits are delimited by comma 1396 | * 1397 | * @param number Input number 1398 | * @return formatted String 1399 | */ 1400 | public static String formatNumber(long number) { 1401 | String stringRepresentation = Long.toString(number); 1402 | StringBuilder sb = new StringBuilder(); 1403 | int bound = stringRepresentation.length() - 1; 1404 | String delimiter = ","; 1405 | int counter = 0; 1406 | for (int i = bound; i >= 0; i--) { 1407 | char c = stringRepresentation.charAt(i); 1408 | if (i != bound && counter % 3 == 0) { 1409 | sb.append(delimiter); 1410 | } 1411 | sb.append(c); 1412 | counter++; 1413 | } 1414 | return sb.reverse().toString(); 1415 | } 1416 | 1417 | public static String[] chop(String input, int step) { 1418 | if (input == null || input.length() == 0) { 1419 | return EMPTY_ARRAY; 1420 | } 1421 | if (step == 0) { 1422 | return new String[]{input}; 1423 | } 1424 | int strLength = input.length(); 1425 | int iterations = strLength % step == 0 ? strLength / step : strLength / step + 1; 1426 | return IntStream.iterate(0, i -> i + step) 1427 | .limit(iterations) 1428 | .mapToObj(i -> input.substring(i, (i + step) < strLength ? i + step : strLength)) 1429 | .toArray(String[]::new); 1430 | } 1431 | 1432 | /** 1433 | * Converts a String into its Start Case version 1434 | * https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage 1435 | * 1436 | * @param input The input String 1437 | * @return Start Case String 1438 | */ 1439 | public static String startCase(final String input) { 1440 | validate(input, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1441 | // split into a word when we encounter a space, or an underscore, or a dash, or a switch from lower to upper case 1442 | String[] words = words(input, "\\s|_|-|(?<=[a-z])(?=[A-Z])"); 1443 | return Arrays.stream(words).filter(w -> !w.trim().isEmpty()) 1444 | .map(w -> upperFirst(w.toLowerCase())).collect(joining(" ")); 1445 | } 1446 | 1447 | public static String escapeRegExp(final String input) { 1448 | validate(input, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER); 1449 | return input.replaceAll("[\\\\\\^\\$\\*\\+\\-\\?\\.\\|\\(\\)\\{\\}\\[\\]]", "\\\\$0"); 1450 | } 1451 | 1452 | private static void validate(String value, Predicate predicate, final Supplier supplier) { 1453 | if (predicate.test(value)) { 1454 | throw new IllegalArgumentException(supplier.get()); 1455 | } 1456 | } 1457 | 1458 | private static long countSubstr(String value, String subStr, boolean allowOverlapping, long count) { 1459 | int position = value.indexOf(subStr); 1460 | if (position == -1) { 1461 | return count; 1462 | } 1463 | int offset; 1464 | if (!allowOverlapping) { 1465 | offset = position + subStr.length(); 1466 | } else { 1467 | offset = position + 1; 1468 | } 1469 | return countSubstr(value.substring(offset), subStr, allowOverlapping, ++count); 1470 | } 1471 | 1472 | private static boolean isNullOrEmpty(String input) { 1473 | return input == null || input.isEmpty(); 1474 | } 1475 | 1476 | } 1477 | 1478 | -------------------------------------------------------------------------------- /src/test/java/strman/StrmanTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * The MIT License 4 | * * 5 | * * Copyright 2016 Shekhar Gulati . 6 | * * 7 | * * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * * of this software and associated documentation files (the "Software"), to deal 9 | * * in the Software without restriction, including without limitation the rights 10 | * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * * copies of the Software, and to permit persons to whom the Software is 12 | * * furnished to do so, subject to the following conditions: 13 | * * 14 | * * The above copyright notice and this permission notice shall be included in 15 | * * all copies or substantial portions of the Software. 16 | * * 17 | * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | package strman; 28 | 29 | import java.util.Arrays; 30 | import java.util.Collections; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | import java.util.Optional; 34 | 35 | import org.junit.Ignore; 36 | import org.junit.Test; 37 | 38 | import static java.util.Arrays.asList; 39 | import static java.util.Collections.singletonList; 40 | import static java.util.stream.Collectors.toList; 41 | import static org.hamcrest.CoreMatchers.*; 42 | import static org.hamcrest.collection.IsArrayContaining.hasItemInArray; 43 | import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; 44 | import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize; 45 | import static org.hamcrest.collection.IsArrayWithSize.emptyArray; 46 | import static org.hamcrest.collection.IsEmptyCollection.empty; 47 | import static org.junit.Assert.*; 48 | import static strman.Strman.*; 49 | import static strman.Strman.endsWith; 50 | 51 | public class StrmanTests { 52 | 53 | @Test 54 | public void append_shouldAppendStringsToEndOfValue() throws Exception { 55 | assertThat(append("f", "o", "o", "b", "a", "r"), equalTo("foobar")); 56 | assertThat(append("foobar"), equalTo("foobar")); 57 | assertThat(append("", "foobar"), equalTo("foobar")); 58 | } 59 | 60 | @Test(expected = IllegalArgumentException.class) 61 | public void append_shouldThrowIllegalArgumentExceptionWhenValueIsNull() throws Exception { 62 | append(null); 63 | } 64 | 65 | @Test 66 | public void appendArray_shouldAppendStringArrayToEndOfValue() throws Exception { 67 | assertThat(appendArray("f", new String[]{"o", "o", "b", "a", "r"}), equalTo("foobar")); 68 | assertThat(appendArray("foobar", new String[]{}), equalTo("foobar")); 69 | assertThat(appendArray("", new String[]{"foobar"}), equalTo("foobar")); 70 | } 71 | 72 | @Test(expected = IllegalArgumentException.class) 73 | public void appendArray_ShouldThrowIllegalArgumentExceptionWhenValueIsNull() throws Exception { 74 | appendArray(null, new String[]{}); 75 | } 76 | 77 | @Test 78 | public void at_shouldFindCharacterAtIndex() throws Exception { 79 | assertThat(at("foobar", 0), equalTo(Optional.of("f"))); 80 | assertThat(at("foobar", 1), equalTo(Optional.of("o"))); 81 | assertThat(at("foobar", -1), equalTo(Optional.of("r"))); 82 | assertThat(at("foobar", -2), equalTo(Optional.of("a"))); 83 | assertThat(at("foobar", 10), equalTo(Optional.empty())); 84 | assertThat(at("foobar", -10), equalTo(Optional.empty())); 85 | } 86 | 87 | @Test 88 | public void between_shouldReturnArrayWithStringsBetweenStartAndEnd() throws Exception { 89 | assertThat(between("[abc][def]", "[", "]"), arrayContaining("abc", "def")); 90 | assertThat(between("foo", "", ""), arrayContaining("foo")); 91 | assertThat(between("foobar", "", ""), arrayContaining("foo", "bar")); 92 | } 93 | 94 | @Test 95 | public void between_shouldReturnEmptyArrayWhenStartAndEndDoesNotExist() throws Exception { 96 | assertThat(between("[abc][def]", "{", "}").length, equalTo(0)); 97 | assertThat(between("", "{", "}").length, equalTo(0)); 98 | } 99 | 100 | @Test 101 | public void chars_shouldReturnAllCharactersInString() throws Exception { 102 | final String title = "title"; 103 | assertThat(chars(title), equalTo(new String[]{"t", "i", "t", "l", "e"})); 104 | } 105 | 106 | @Test 107 | public void collapseWhitespace_shouldReplaceConsecutiveWhitespaceWithSingleSpace() throws Exception { 108 | String[] fixture = { 109 | "foo bar", 110 | " foo bar ", 111 | " foo bar ", 112 | " foo bar " 113 | }; 114 | Arrays.stream(fixture).forEach(el -> assertThat(collapseWhitespace(el), equalTo("foo bar"))); 115 | } 116 | 117 | @Test 118 | public void collapseWhitespace_shouldReplaceConsecutiveWhitespaceBetweenMultipleStrings() throws Exception { 119 | String input = " foo bar bazz hello world "; 120 | assertThat(collapseWhitespace(input), equalTo("foo bar bazz hello world")); 121 | } 122 | 123 | @Test 124 | public void containsWithCaseSensitiveFalse_shouldReturnTrueWhenStringContainsNeedle() throws Exception { 125 | String[] fixture = { 126 | "foo bar", 127 | "bar foo", 128 | "foobar", 129 | "foo" 130 | }; 131 | 132 | Arrays.stream(fixture).forEach(el -> assertTrue(contains(el, "FOO"))); 133 | } 134 | 135 | @Test 136 | public void containsWithCaseSensitiveTrue_shouldReturnTrueWhenStringContainsNeedle() throws Exception { 137 | String[] fixture = { 138 | "foo bar", 139 | "bar foo", 140 | "foobar", 141 | "foo" 142 | }; 143 | 144 | Arrays.stream(fixture).forEach(el -> assertFalse(contains(el, "FOO", true))); 145 | } 146 | 147 | @Test 148 | public void containsAll_shouldReturnTrueOnlyWhenAllNeedlesAreContainedInValue() throws Exception { 149 | String[] fixture = { 150 | "foo bar", 151 | "bar foo", 152 | "foobar", 153 | }; 154 | 155 | Arrays.stream(fixture).forEach(el -> assertTrue(containsAll(el, new String[]{"foo", "bar"}))); 156 | } 157 | 158 | @Test 159 | public void containsAll_shouldReturnFalseOnlyWhenAllNeedlesAreNotContainedInValue() throws Exception { 160 | String[] fixture = { 161 | "foo bar", 162 | "bar foo", 163 | "foobar", 164 | }; 165 | Arrays.stream(fixture).forEach(el -> assertFalse(containsAll(el, new String[]{"FOO", "bar"}, true))); 166 | } 167 | 168 | @Test 169 | public void containsAny_shouldReturnTrueWhenAnyOfSearchNeedleExistInInputValue() throws Exception { 170 | String[] fixture = { 171 | "foo bar", 172 | "bar foo", 173 | "foobar", 174 | }; 175 | Arrays.stream(fixture).forEach(el -> assertTrue(containsAny(el, new String[]{"foo", "bar", "test"}))); 176 | } 177 | 178 | @Test 179 | public void containsAny_shouldReturnFalseWhenNoneOfSearchNeedleExistInInputValue() throws Exception { 180 | String[] fixture = { 181 | "foo bar", 182 | "bar foo", 183 | "foobar", 184 | }; 185 | Arrays.stream(fixture).forEach(el -> assertFalse(containsAny(el, new String[]{"FOO", "BAR", "Test"}, true))); 186 | } 187 | 188 | @Test 189 | public void countSubstr_shouldCountSubStrCountCaseInsensitiveWithoutOverlapInValue() throws Exception { 190 | assertThat(countSubstr("aaaAAAaaa", "aaa", false, false), equalTo(3L)); 191 | } 192 | 193 | @Test 194 | public void countSubstr_shouldCountSubStrCountCaseSensitiveWithoutOverlapInValue() throws Exception { 195 | assertThat(countSubstr("aaaAAAaaa", "aaa"), equalTo(2L)); 196 | } 197 | 198 | @Test 199 | public void countSubstr_shouldCountSubStrCountCaseInsensitiveWithOverlapInValue() throws Exception { 200 | assertThat(countSubstr("aaaAAAaaa", "aaa", false, true), equalTo(7L)); 201 | } 202 | 203 | @Test 204 | public void countSubstr_shouldCountSubStrCountCaseSensitiveWithOverlapInValue() throws Exception { 205 | assertThat(countSubstr("aaaAAAaaa", "AAA", true, true), equalTo(1L)); 206 | } 207 | 208 | @Test 209 | public void countSubstrTestFixture_caseSensitiveTrueAndOverlappingFalse() throws Exception { 210 | String[] fixture = { 211 | "aaaaaAaaAA", 212 | "faaaAAaaaaAA", 213 | "aaAAaaaaafA", 214 | "AAaaafaaaaAAAA" 215 | }; 216 | Arrays.stream(fixture).forEach(el -> assertThat(countSubstr(el, "a", true, false), equalTo(7L))); 217 | } 218 | 219 | @Test 220 | public void countSubstrTestFixture_caseSensitiveFalseAndOverlappingFalse() throws Exception { 221 | String[] fixture = { 222 | "aaaaaaa", 223 | "faaaaaaa", 224 | "aaaaaaaf", 225 | "aaafaaaa" 226 | }; 227 | Arrays.stream(fixture).forEach(el -> assertThat(countSubstr(el, "A", false, false), equalTo(7L))); 228 | } 229 | 230 | @Test 231 | public void countSubstrTestFixture_caseSensitiveTrueAndOverlappingTrue() throws Exception { 232 | assertThat(countSubstr("aaa", "aa", true, true), equalTo(2L)); 233 | } 234 | 235 | @Test 236 | public void endsWith_caseSensitive_ShouldBeTrueWhenStringEndsWithSearchStr() throws Exception { 237 | String[] fixture = { 238 | "foo bar", 239 | "bar" 240 | }; 241 | Arrays.stream(fixture).forEach(el -> assertTrue(endsWith(el, "bar"))); 242 | } 243 | 244 | @Test 245 | public void endsWith_notCaseSensitive_ShouldBeTrueWhenStringEndsWithSearchStr() throws Exception { 246 | String[] fixture = { 247 | "foo bar", 248 | "bar" 249 | }; 250 | Arrays.stream(fixture).forEach(el -> assertTrue(endsWith(el, "BAR", false))); 251 | } 252 | 253 | @Test 254 | public void endsWith_caseSensitiveAtPosition_ShouldBeTrueWhenStringEndsWithSearchStr() throws Exception { 255 | String[] fixture = { 256 | "foo barr", 257 | "barr" 258 | }; 259 | Arrays.stream(fixture).forEach(el -> assertTrue(endsWith(el, "bar", el.length() - 1, true))); 260 | } 261 | 262 | @Test 263 | public void endsWith_notCaseSensitiveAtPosition_ShouldBeTrueWhenStringEndsWithSearchStr() throws Exception { 264 | String[] fixture = { 265 | "foo barr", 266 | "barr" 267 | }; 268 | Arrays.stream(fixture).forEach(el -> assertTrue(endsWith(el, "BAR", el.length() - 1, false))); 269 | } 270 | 271 | @Test 272 | public void ensureLeft_shouldEnsureValueStartsWithFoo() throws Exception { 273 | String[] fixture = { 274 | "foobar", 275 | "bar" 276 | }; 277 | 278 | Arrays.stream(fixture).forEach(el -> assertThat(ensureLeft(el, "foo"), equalTo("foobar"))); 279 | } 280 | 281 | @Test 282 | public void ensureLeft_notCaseSensitive_shouldEnsureValueStartsWithFoo() throws Exception { 283 | assertThat(ensureLeft("foobar", "FOO", false), equalTo("foobar")); 284 | assertThat(ensureLeft("bar", "FOO", false), equalTo("FOObar")); 285 | } 286 | 287 | @Test 288 | public void base64Decode_shouldDecodeABase64DecodedValueToString() throws Exception { 289 | assertThat(base64Decode("c3RybWFu"), equalTo("strman")); 290 | assertThat(base64Decode("Zm9v"), equalTo("foo")); 291 | assertThat(base64Decode("YmFy"), equalTo("bar")); 292 | assertThat(base64Decode("YsOhciE="), equalTo("bár!")); 293 | assertThat(base64Decode("5ryi"), equalTo("漢")); 294 | } 295 | 296 | @Test 297 | public void base64Encode_shouldEncodeAString() throws Exception { 298 | assertThat(base64Encode("strman"), equalTo("c3RybWFu")); 299 | assertThat(base64Encode("foo"), equalTo("Zm9v")); 300 | assertThat(base64Encode("bar"), equalTo("YmFy")); 301 | assertThat(base64Encode("bár!"), equalTo("YsOhciE=")); 302 | assertThat(base64Encode("漢"), equalTo("5ryi")); 303 | } 304 | 305 | @Test 306 | public void binDecode_shouldDecodeABinaryStringToAValue() throws Exception { 307 | assertThat( 308 | binDecode("000000000111001100000000011101000000000001110010000000000110110100000000011000010000000001101110"), 309 | equalTo("strman")); 310 | 311 | assertThat(binDecode("0110111100100010"), equalTo("漢")); 312 | assertThat(binDecode("0000000001000001"), equalTo("A")); 313 | assertThat(binDecode("0000000011000001"), equalTo("Á")); 314 | assertThat(binDecode("00000000010000010000000001000001"), equalTo("AA")); 315 | } 316 | 317 | @Test 318 | public void binEncode_shouldEncodeAStringToBinaryFormat() throws Exception { 319 | assertThat(binEncode("漢"), equalTo("0110111100100010")); 320 | assertThat(binEncode("A"), equalTo("0000000001000001")); 321 | assertThat(binEncode("Á"), equalTo("0000000011000001")); 322 | assertThat(binEncode("AA"), equalTo("00000000010000010000000001000001")); 323 | } 324 | 325 | @Test 326 | public void decDecode_shouldDecodeDecimalStringToString() throws Exception { 327 | assertThat(decDecode("28450"), equalTo("漢")); 328 | assertThat(decDecode("00065"), equalTo("A")); 329 | assertThat(decDecode("00193"), equalTo("Á")); 330 | assertThat(decDecode("0006500065"), equalTo("AA")); 331 | } 332 | 333 | @Test 334 | public void decEncode_shouldEncodeStringToDecimal() throws Exception { 335 | assertThat(decEncode("漢"), equalTo("28450")); 336 | assertThat(decEncode("A"), equalTo("00065")); 337 | assertThat(decEncode("Á"), equalTo("00193")); 338 | assertThat(decEncode("AA"), equalTo("0006500065")); 339 | } 340 | 341 | @Test 342 | public void ensureRight_shouldEnsureStringEndsWithBar() throws Exception { 343 | final String[] fixture = { 344 | "foo", "foobar", "fooBAR" 345 | }; 346 | assertThat(Arrays.stream(fixture).map(el -> ensureRight(el, "bar", false)).collect(toList()), hasItems("foobar", "foobar", "fooBAR")); 347 | assertThat(Arrays.stream(fixture).map(el -> ensureRight(el, "bar")).collect(toList()), hasItems("foobar", "foobar", "fooBARbar")); 348 | } 349 | 350 | @Test 351 | public void first_shouldReturnFirstThreeCharsOfString() throws Exception { 352 | final String[] fixture = { 353 | "foo", "foobar" 354 | }; 355 | Arrays.stream(fixture).forEach(el -> assertThat(first(el, 3), equalTo(Optional.of("foo")))); 356 | } 357 | 358 | @Test 359 | public void head_shouldReturnFirstCharOfString() throws Exception { 360 | final String[] fixture = { 361 | "foo", "foobar" 362 | }; 363 | 364 | Arrays.stream(fixture).forEach(el -> assertThat(head(el), equalTo(Optional.of("f")))); 365 | } 366 | 367 | @Test 368 | public void format_shouldFormatStringsToFooBar() throws Exception { 369 | assertThat(format("{0} bar", "foo"), equalTo("foo bar")); 370 | assertThat(format("foo {0}", "bar"), equalTo("foo bar")); 371 | assertThat(format("foo {0}", "bar", "foo"), equalTo("foo bar")); 372 | assertThat(format("{0} {1}", "foo", "bar"), equalTo("foo bar")); 373 | assertThat(format("{1} {0}", "bar", "foo"), equalTo("foo bar")); 374 | } 375 | 376 | @Test(expected = IllegalArgumentException.class) 377 | public void format_shouldThrowExceptionWhenValueDoesNotExist() throws Exception { 378 | assertThat(format("{1} {0}"), equalTo("{1} {0}")); 379 | } 380 | 381 | @Test 382 | public void hexDecode_shouldDecodeHexCodeToString() throws Exception { 383 | assertThat(hexDecode("6f22"), equalTo("漢")); 384 | assertThat(hexDecode("0041"), equalTo("A")); 385 | assertThat(hexDecode("00c1"), equalTo("Á")); 386 | assertThat(hexDecode("00410041"), equalTo("AA")); 387 | } 388 | 389 | @Test 390 | public void hexEncode_shouldEncodeStringToHexadecimalFormat() throws Exception { 391 | assertThat(hexEncode("漢"), equalTo("6f22")); 392 | assertThat(hexEncode("A"), equalTo("0041")); 393 | assertThat(hexEncode("Á"), equalTo("00c1")); 394 | assertThat(hexEncode("AA"), equalTo("00410041")); 395 | } 396 | 397 | @Test 398 | public void indexOf_shouldBeTrueWhenNeedleExists() throws Exception { 399 | final String value = "foobar"; 400 | assertThat(indexOf(value, "f", 0, true), equalTo(0)); 401 | assertThat(indexOf(value, "o", 0, true), equalTo(1)); 402 | assertThat(indexOf(value, "b", 0, true), equalTo(3)); 403 | assertThat(indexOf(value, "a", 0, true), equalTo(4)); 404 | assertThat(indexOf(value, "r", 0, true), equalTo(5)); 405 | assertThat(indexOf(value, "t", 0, true), equalTo(-1)); 406 | } 407 | 408 | @Test 409 | public void indexOf_shouldBeTrueWhenNeedleExistCaseSensitive() throws Exception { 410 | final String value = "foobar"; 411 | assertThat(indexOf(value, "F", 0, false), equalTo(0)); 412 | assertThat(indexOf(value, "O", 0, false), equalTo(1)); 413 | assertThat(indexOf(value, "B", 0, false), equalTo(3)); 414 | assertThat(indexOf(value, "A", 0, false), equalTo(4)); 415 | assertThat(indexOf(value, "R", 0, false), equalTo(5)); 416 | assertThat(indexOf(value, "T", 0, false), equalTo(-1)); 417 | } 418 | 419 | @Test 420 | public void inequal_shouldTestInequalityOfStrings() throws Exception { 421 | assertThat(unequal("a", "b"), equalTo(true)); 422 | assertThat(unequal("a", "a"), equalTo(false)); 423 | assertThat(unequal("0", "1"), equalTo(true)); 424 | } 425 | 426 | @Test 427 | public void insert_shouldInsertStringAtIndex() throws Exception { 428 | assertThat(insert("fbar", "oo", 1), equalTo("foobar")); 429 | assertThat(insert("foo", "bar", 3), equalTo("foobar")); 430 | assertThat(insert("foobar", "x", 5), equalTo("foobaxr")); 431 | assertThat(insert("foobar", "x", 6), equalTo("foobarx")); 432 | assertThat(insert("foo bar", "asadasd", 100), equalTo("foo bar")); 433 | } 434 | 435 | @Test 436 | public void isLowerCase_shouldBeTrueWhenStringIsLowerCase() throws Exception { 437 | assertThat(isLowerCase(""), equalTo(true)); 438 | assertThat(isLowerCase("foo"), equalTo(true)); 439 | assertThat(isLowerCase("foobarfoo"), equalTo(true)); 440 | } 441 | 442 | @Test 443 | public void isLowerCase_shouldBeFalseWhenStringIsNotLowerCase() throws Exception { 444 | assertThat(isLowerCase("Foo"), equalTo(false)); 445 | assertThat(isLowerCase("foobarfooA"), equalTo(false)); 446 | } 447 | 448 | @Test 449 | public void isUpperCase_shouldBeTrueWhenStringIsUpperCase() throws Exception { 450 | assertThat(isUpperCase(""), equalTo(true)); 451 | assertThat(isUpperCase("FOO"), equalTo(true)); 452 | assertThat(isUpperCase("FOOBARFOO"), equalTo(true)); 453 | } 454 | 455 | @Test 456 | public void isUpperCase_shouldBeFalseWhenStringIsNotUpperCase() throws Exception { 457 | assertThat(isUpperCase("Foo"), equalTo(false)); 458 | assertThat(isUpperCase("foobarfooA"), equalTo(false)); 459 | } 460 | 461 | @Test 462 | public void last_shouldReturnLastNChars() throws Exception { 463 | assertThat(last("foo", 3), equalTo("foo")); 464 | assertThat(last("foobarfoo", 3), equalTo("foo")); 465 | assertThat(last("", 3), equalTo("")); 466 | assertThat(last("f", 3), equalTo("f")); 467 | } 468 | 469 | @Test 470 | public void leftPad_shouldAddPaddingOnTheLeft() throws Exception { 471 | assertThat(leftPad("1", "0", 5), equalTo("00001")); 472 | assertThat(leftPad("01", "0", 5), equalTo("00001")); 473 | assertThat(leftPad("001", "0", 5), equalTo("00001")); 474 | assertThat(leftPad("0001", "0", 5), equalTo("00001")); 475 | assertThat(leftPad("00001", "0", 5), equalTo("00001")); 476 | } 477 | 478 | @Test 479 | public void isString_shouldBeFalseWhenValueIsNotString() throws Exception { 480 | assertFalse(isString(1)); 481 | assertFalse(isString(false)); 482 | assertFalse(isString(1.2)); 483 | assertFalse(isString(new String[]{})); 484 | } 485 | 486 | @Test 487 | public void isString_shouldBeTrueWhenValueIsString() throws Exception { 488 | assertTrue(isString("string")); 489 | assertTrue(isString("")); 490 | } 491 | 492 | @Test 493 | public void lastIndexOf_shouldFindIndexOfNeedle() throws Exception { 494 | final String value = "foobarfoobar"; 495 | assertThat(lastIndexOf(value, "f"), equalTo(6)); 496 | assertThat(lastIndexOf(value, "o"), equalTo(8)); 497 | assertThat(lastIndexOf(value, "b"), equalTo(9)); 498 | assertThat(lastIndexOf(value, "a"), equalTo(10)); 499 | assertThat(lastIndexOf(value, "r"), equalTo(11)); 500 | assertThat(lastIndexOf(value, "t"), equalTo(-1)); 501 | } 502 | 503 | @Test 504 | public void lastIndexOf_shouldFindIndexOfNeedleCaseInsensitive() throws Exception { 505 | final String value = "foobarfoobar"; 506 | assertThat(lastIndexOf(value, "F", false), equalTo(6)); 507 | assertThat(lastIndexOf(value, "O", false), equalTo(8)); 508 | assertThat(lastIndexOf(value, "B", false), equalTo(9)); 509 | assertThat(lastIndexOf(value, "A", false), equalTo(10)); 510 | assertThat(lastIndexOf(value, "R", false), equalTo(11)); 511 | assertThat(lastIndexOf(value, "T", false), equalTo(-1)); 512 | } 513 | 514 | @Test 515 | public void leftTrim_shouldRemoveSpacesOnLeft() throws Exception { 516 | assertThat(leftTrim(" strman"), equalTo("strman")); 517 | assertThat(leftTrim(" strman "), equalTo("strman ")); 518 | } 519 | 520 | @Test 521 | public void prepend_shouldPrependStrings() throws Exception { 522 | assertThat(prepend("r", "f", "o", "o", "b", "a"), equalTo("foobar")); 523 | assertThat(prepend("foobar"), equalTo("foobar")); 524 | assertThat(prepend("", "foobar"), equalTo("foobar")); 525 | assertThat(prepend("bar", "foo"), equalTo("foobar")); 526 | } 527 | 528 | @Test 529 | public void prependArray_shouldPrependStrings() throws Exception { 530 | assertThat(prependArray("r", new String[]{"f", "o", "o", "b", "a"}), equalTo("foobar")); 531 | assertThat(prependArray("foobar", new String[0]), equalTo("foobar")); 532 | assertThat(prependArray("", new String[]{"foobar"}), equalTo("foobar")); 533 | assertThat(prependArray("bar", new String[]{"foo"}), equalTo("foobar")); 534 | } 535 | 536 | @Test 537 | public void removeEmptyStrings_shouldRemoveEmptyStrings() throws Exception { 538 | assertThat(removeEmptyStrings(new String[]{"aa", "", " ", "bb", "cc", null}), arrayContaining("aa", "bb", "cc")); 539 | assertThat(removeEmptyStrings(new String[0]), emptyArray()); 540 | } 541 | 542 | @Test 543 | public void removeLeft_shouldRemoveStringFromLeft() throws Exception { 544 | final String[] fixture = { 545 | "foobar", 546 | "bar" 547 | }; 548 | 549 | Arrays.stream(fixture).forEach(el -> assertThat(removeLeft(el, "foo"), equalTo("bar"))); 550 | assertThat(removeLeft("barfoo", "foo"), equalTo("barfoo")); 551 | assertThat(removeLeft("foofoo", "foo"), equalTo("foo")); 552 | } 553 | 554 | @Test 555 | public void removeLeft_shouldRemoveStringFromLeftCaseInSensitive() throws Exception { 556 | final String[] fixture = { 557 | "foobar", 558 | "bar" 559 | }; 560 | 561 | Arrays.stream(fixture).forEach(el -> assertThat(removeLeft(el, "FOO", false), equalTo("bar"))); 562 | } 563 | 564 | @Test 565 | public void removeNonWords_shouldRemoveAllNonWordsFromInputString() throws Exception { 566 | 567 | final String[] fixture = { 568 | "foo bar", 569 | "foo&bar-", 570 | "foobar" 571 | }; 572 | 573 | Arrays.stream(fixture).forEach(el -> assertThat(removeNonWords(el), equalTo("foobar"))); 574 | } 575 | 576 | @Test 577 | public void removeRight_shouldRemoveStringFromRight() throws Exception { 578 | final String[] fixture = { 579 | "foobar", 580 | "foo" 581 | }; 582 | 583 | Arrays.stream(fixture).forEach(el -> assertThat(removeRight(el, "bar"), equalTo("foo"))); 584 | assertThat(removeRight("barfoo", "bar"), equalTo("barfoo")); 585 | assertThat(removeRight("barbar", "bar"), equalTo("bar")); 586 | } 587 | 588 | @Test 589 | public void removeRight_shouldRemoveStringFromRightCaseInSensitive() throws Exception { 590 | final String[] fixture = { 591 | "foobar", 592 | "foo" 593 | }; 594 | 595 | Arrays.stream(fixture).forEach(el -> assertThat(removeRight(el, "BAR", false), equalTo("foo"))); 596 | } 597 | 598 | @Test 599 | public void removeSpaces_shouldRemoveSpacesInTheString() throws Exception { 600 | final String[] fixture = { 601 | "foo bar", 602 | "foo bar ", 603 | " foo bar", 604 | " foo bar " 605 | }; 606 | Arrays.stream(fixture).forEach(el -> assertThat(removeSpaces(el), equalTo("foobar"))); 607 | } 608 | 609 | @Test 610 | public void repeat_shouldRepeatAStringNTimes() throws Exception { 611 | assertThat(repeat("1", 1), equalTo("1")); 612 | assertThat(repeat("1", 2), equalTo("11")); 613 | assertThat(repeat("1", 3), equalTo("111")); 614 | assertThat(repeat("1", 4), equalTo("1111")); 615 | assertThat(repeat("1", 5), equalTo("11111")); 616 | } 617 | 618 | @Test 619 | public void replace_shouldReplaceAllOccurrencesOfString() throws Exception { 620 | assertThat(replace("foo bar", "foo", "bar", true), equalTo("bar bar")); 621 | assertThat(replace("foo bar foo", "foo", "bar", true), equalTo("bar bar bar")); 622 | } 623 | 624 | @Test 625 | public void replace_shouldReplaceAllOccurrencesOfStringCaseSensitive() throws Exception { 626 | assertThat(replace("FOO bar", "foo", "bar", false), equalTo("bar bar")); 627 | assertThat(replace("FOO bar foo", "foo", "bar", false), equalTo("bar bar bar")); 628 | } 629 | 630 | @Test 631 | public void reverse_shouldReverseInputString() throws Exception { 632 | assertThat(reverse(""), equalTo("")); 633 | assertThat(reverse("foo"), equalTo("oof")); 634 | assertThat(reverse("shekhar"), equalTo("rahkehs")); 635 | assertThat(reverse("bar"), equalTo("rab")); 636 | assertThat(reverse("foo_"), equalTo("_oof")); 637 | assertThat(reverse("f"), equalTo("f")); 638 | } 639 | 640 | @Test 641 | public void rightPad_shouldRightPadAString() throws Exception { 642 | assertThat(rightPad("1", "0", 5), equalTo("10000")); 643 | assertThat(rightPad("10", "0", 5), equalTo("10000")); 644 | assertThat(rightPad("100", "0", 5), equalTo("10000")); 645 | assertThat(rightPad("1000", "0", 5), equalTo("10000")); 646 | assertThat(rightPad("10000", "0", 5), equalTo("10000")); 647 | assertThat(rightPad("10000000", "0", 5), equalTo("10000000")); 648 | } 649 | 650 | @Test 651 | public void rightTrim_shouldRemoveSpacesFromTheRight() throws Exception { 652 | assertThat(rightTrim("strman "), equalTo("strman")); 653 | assertThat(rightTrim(" strman"), equalTo(" strman")); 654 | assertThat(rightTrim("strman"), equalTo("strman")); 655 | } 656 | 657 | @Test 658 | public void safeTruncate_shouldSafelyTruncateStrings() throws Exception { 659 | assertThat(safeTruncate("foo bar", 0, "."), equalTo("")); 660 | assertThat(safeTruncate("foo bar", 4, "."), equalTo("foo.")); 661 | assertThat(safeTruncate("foo bar", 3, "."), equalTo(".")); 662 | assertThat(safeTruncate("foo bar", 2, "."), equalTo(".")); 663 | assertThat(safeTruncate("foo bar", 7, "."), equalTo("foo bar")); 664 | assertThat(safeTruncate("foo bar", 8, "."), equalTo("foo bar")); 665 | assertThat(safeTruncate("A Javascript string manipulation library.", 16, "..."), equalTo("A Javascript...")); 666 | assertThat(safeTruncate("A Javascript string manipulation library.", 15, "..."), equalTo("A Javascript...")); 667 | assertThat(safeTruncate("A Javascript string manipulation library.", 14, "..."), equalTo("A...")); 668 | assertThat(safeTruncate("A Javascript string manipulation library.", 13, "..."), equalTo("A...")); 669 | } 670 | 671 | @Test 672 | public void truncate_shouldTruncateString() throws Exception { 673 | assertThat(truncate("foo bar", 0, "."), equalTo("")); 674 | assertThat(truncate("foo bar", 3, "."), equalTo("fo.")); 675 | assertThat(truncate("foo bar", 2, "."), equalTo("f.")); 676 | assertThat(truncate("foo bar", 4, "."), equalTo("foo.")); 677 | assertThat(truncate("foo bar", 7, "."), equalTo("foo bar")); 678 | assertThat(truncate("foo bar", 8, "."), equalTo("foo bar")); 679 | assertThat(truncate("A Javascript string manipulation library.", 16, "..."), equalTo("A Javascript ...")); 680 | assertThat(truncate("A Javascript string manipulation library.", 15, "..."), equalTo("A Javascript...")); 681 | assertThat(truncate("A Javascript string manipulation library.", 14, "..."), equalTo("A Javascrip...")); 682 | } 683 | 684 | @Test 685 | public void htmlDecode_shouldDecodeToHtml() throws Exception { 686 | assertThat(htmlDecode("á"), equalTo("\u00E1")); 687 | assertThat(htmlDecode("Ш"), equalTo("Ш")); 688 | assertThat(htmlDecode("Ж"), equalTo("Ж")); 689 | assertThat(htmlDecode("┐"), equalTo("┐")); 690 | } 691 | 692 | @Test 693 | public void htmlEncode_shouldBeEncodedToHtmlEntities() throws Exception { 694 | assertThat(htmlEncode("á"), equalTo("á")); 695 | assertThat(htmlEncode("áéíóú"), equalTo("áéíóú")); 696 | assertThat(htmlEncode("Ш"), equalTo("Ш")); 697 | assertThat(htmlEncode("Ж"), equalTo("Ж")); 698 | assertThat(htmlEncode("┐"), equalTo("┐")); 699 | } 700 | 701 | @Test 702 | public void shuffle_shouldShuffleAString() throws Exception { 703 | assertThat(shuffle("shekhar"), not(equalTo("shekhar"))); 704 | assertThat(shuffle("strman"), not(equalTo("strman"))); 705 | assertThat(shuffle(""), equalTo("")); 706 | assertThat(shuffle("s"), equalTo("s")); 707 | } 708 | 709 | @Test 710 | public void slugify_shouldBeFooBar() throws Exception { 711 | String[] fixture = { 712 | "foo bar", 713 | "foo bar.", 714 | "foo bar ", 715 | " foo bar", 716 | " foo bar ", 717 | "foo------bar", 718 | "fóõ bár", 719 | "foo ! bar", 720 | "foo ~~ bar", 721 | "foo bar", 722 | "FOO bar" 723 | }; 724 | 725 | Arrays.stream(fixture).forEach(el -> assertThat(String.format("slugify(%s) should be foo-bar ", el), slugify(el), equalTo("foo-bar"))); 726 | } 727 | 728 | @Test 729 | public void slugify_shouldBeFooAndBar() throws Exception { 730 | String[] fixture = { 731 | "foo&bar", 732 | "foo&bar.", 733 | "foo&bar ", 734 | " foo&bar", 735 | " foo&bar ", 736 | "foo&bar", 737 | "fóõ-and---bár", 738 | "foo & bar", 739 | "FOO & bar" 740 | }; 741 | 742 | Arrays.stream(fixture).forEach(el -> assertThat(String.format("slugify(%s) should be foo-and-bar ", el), slugify(el), equalTo("foo-and-bar"))); 743 | } 744 | 745 | @Test 746 | public void transliterate_shouldTransliterateTheText() throws Exception { 747 | assertThat(transliterate("fóõ bár"), equalTo("foo bar")); 748 | } 749 | 750 | @Test 751 | public void surround_shouldSurroundStringWithPrefixAndSuffix() throws Exception { 752 | assertThat(surround("foo", "bar", null), equalTo("barfoobar")); 753 | assertThat(surround("shekhar", "***", null), equalTo("***shekhar***")); 754 | assertThat(surround("", ">", null), equalTo(">>")); 755 | assertThat(surround("bar", "", null), equalTo("bar")); 756 | assertThat(surround("f", null, null), equalTo("f")); 757 | assertThat(surround("div", "<", ">"), equalTo("
")); 758 | } 759 | 760 | @Test 761 | public void toCamelCase_shouldConvertStringToCamelCase() throws Exception { 762 | String[] fixture = { 763 | "CamelCase", 764 | "camelCase", 765 | "Camel case", 766 | "Camel case", 767 | "camel Case", 768 | "camel-case", 769 | "-camel--case", 770 | "camel_case", 771 | " camel_case", 772 | }; 773 | Arrays.stream(fixture).forEach(el -> assertThat(String.format("toCameCase(%s) should be camelCase", el), toCamelCase(el), equalTo("camelCase"))); 774 | 775 | assertThat(toCamelCase("c"), equalTo("c")); 776 | } 777 | 778 | @Test 779 | public void toDeCamelCase_shouldDeCamelCaseAString() throws Exception { 780 | String[] fixture = { 781 | "deCamelize", 782 | "de-Camelize", 783 | "de camelize", 784 | "de camelize", 785 | "de Camelize", 786 | "de-camelize", 787 | "-de--camelize", 788 | "de_camelize", 789 | " de_camelize" 790 | }; 791 | 792 | Arrays.stream(fixture).forEach(el -> assertThat(String.format("toDecamelize(%s) should be de-camelize", el), toDecamelize(el, null), equalTo("de camelize"))); 793 | 794 | assertThat(toDecamelize("camelCase", "_"), equalTo("camel_case")); 795 | } 796 | 797 | @Test 798 | public void toKebabCase_shouldKebabCaseAString() throws Exception { 799 | String[] fixture = { 800 | "deCamelize", 801 | "de-Camelize", 802 | "de camelize", 803 | "de camelize", 804 | "de Camelize", 805 | "de-camelize", 806 | "-de--camelize", 807 | "de_camelize", 808 | " de_camelize" 809 | }; 810 | 811 | Arrays.stream(fixture).forEach(el -> 812 | assertThat(String.format("toKebabCase(%s) should be de-camelize", el), toKebabCase(el), equalTo("de-camelize"))); 813 | } 814 | 815 | @Test 816 | public void toSnakeCase_shouldSnakeCaseAString() throws Exception { 817 | String[] fixture = { 818 | "deCamelize", 819 | "de-Camelize", 820 | "de camelize", 821 | "de camelize", 822 | "de Camelize", 823 | "de-camelize", 824 | "-de--camelize", 825 | "de_camelize", 826 | " de_camelize" 827 | }; 828 | 829 | Arrays.stream(fixture).forEach(el -> assertThat(String.format("toSnakeCase(%s) should be de_camelize", el), toSnakeCase(el), equalTo("de_camelize"))); 830 | } 831 | 832 | @Test 833 | public void snakeCase_shouldConvertAStringToSnakecase() throws Exception { 834 | String[] input = { 835 | "Foo Bar", 836 | "fooBar" 837 | }; 838 | 839 | Arrays.stream(input).forEach(el -> 840 | assertThat(String.format("%s should be foo_bar", el), toSnakeCase(el), is(equalTo("foo_bar")))); 841 | 842 | } 843 | 844 | @Test 845 | public void unequal_shouldTestInequalityOfStrings() throws Exception { 846 | assertThat(unequal("a", "b"), equalTo(true)); 847 | assertThat(unequal("a", "a"), equalTo(false)); 848 | assertThat(unequal("0", "1"), equalTo(true)); 849 | } 850 | 851 | 852 | @Test 853 | public void removeLeft_shouldNotLowercaseWhenCaseInsensitive() throws Exception { 854 | String result = removeLeft("This HAS A THIS IN FRONT", "THIS ", false); 855 | assertThat(result, is("HAS A THIS IN FRONT")); 856 | } 857 | 858 | @Test 859 | public void replace_shouldNotLowercaseWhenCaseInsensitive() throws Exception { 860 | String result = replace("One and two and THREE and Four", "and", "&", false); 861 | assertThat(result, is("One & two & THREE & Four")); 862 | } 863 | 864 | @Test 865 | public void removeRight_shouldNotLowercaseWhenCaseInsensitive() throws Exception { 866 | String result = removeRight("Remove the END at the end", " END", false); 867 | assertThat(result, is("Remove the END at the")); 868 | } 869 | 870 | @Test 871 | public void transliterate_shouldDeburrTheString() throws Exception { 872 | String result = transliterate("déjà vu"); 873 | assertThat(result, is(equalTo("deja vu"))); 874 | } 875 | 876 | @Ignore 877 | public void htmlEncode_shouldConvertCharactersToTheirHtmlEntities() throws Exception { 878 | String result = htmlEncode("fred, barney, & pebbles"); 879 | assertThat(result, is(equalTo("fred, barney, & pebbles"))); 880 | } 881 | 882 | @Test 883 | public void kebabCase_shouldConvertAStringToKebabCase() throws Exception { 884 | String[] input = { 885 | "Foo Bar", 886 | "fooBar" 887 | }; 888 | 889 | Arrays.stream(input).forEach(el -> 890 | assertThat(String.format("%s should be foo-bar", el), toKebabCase(el), is(equalTo("foo-bar")))); 891 | 892 | } 893 | 894 | @Test 895 | public void join_shouldJoinArrayOfStringIntoASingleString() throws Exception { 896 | String[] strings = { 897 | "hello", 898 | "world", 899 | "123" 900 | }; 901 | assertThat(join(strings, ";"), is(equalTo("hello;world;123"))); 902 | } 903 | 904 | @Test(expected = IllegalArgumentException.class) 905 | public void join_shouldThrowIllegalArgumentExceptionWhenSeparatorIsNull() throws Exception { 906 | String[] strings = { 907 | "hello", 908 | "world", 909 | "123" 910 | }; 911 | 912 | join(strings, null); 913 | } 914 | 915 | @Test 916 | public void join_shouldReturnEmptyStringWhenInputArrayIsEmpty() throws Exception { 917 | String[] emptyArray = {}; 918 | assertThat(join(emptyArray, ","), is(equalTo(""))); 919 | } 920 | 921 | @Test 922 | public void capitalize_shouldCapitalizeFirstCharacterOfString() throws Exception { 923 | String[] strings = { 924 | "FRED", 925 | "fRED", 926 | "fred" 927 | }; 928 | Arrays.stream(strings).forEach(el -> assertThat(String.format("%s should be Fred", el), capitalize(el), equalTo("Fred"))); 929 | } 930 | 931 | @Test 932 | public void lowerFirst_shouldLowercasedFirstCharacterOfString() throws Exception { 933 | assertThat(lowerFirst("FRED"), is(equalTo("fRED"))); 934 | assertThat(lowerFirst("fred"), is(equalTo("fred"))); 935 | assertThat(lowerFirst("Fred"), is(equalTo("fred"))); 936 | } 937 | 938 | @Test 939 | public void isEnclosedBetween_shouldChekcWhetherStringIsEnclosed() throws Exception { 940 | assertThat(isEnclosedBetween("{{shekhar}}", "{{", "}}"), is(true)); 941 | assertThat(isEnclosedBetween("shekhar", "{{", "}}"), is(false)); 942 | assertThat(isEnclosedBetween("*shekhar*", "*"), is(true)); 943 | assertThat(isEnclosedBetween("shekhar", "*"), is(false)); 944 | } 945 | 946 | @Test(expected = IllegalArgumentException.class) 947 | public void isEnclosedBetween_shouldThrowIllegalArgumentExceptionWhenEncloserIsNull() throws Exception { 948 | assertThat(isEnclosedBetween("shekhar", null), is(false)); 949 | } 950 | 951 | @Test 952 | public void words_shouldConvertTextToWords() throws Exception { 953 | final String line = "This is a string, with words!"; 954 | assertThat(words(line), arrayContaining("This", "is", "a", "string,", "with", "words!")); 955 | } 956 | 957 | @Test 958 | public void upperFirst_shouldConvertFirstCharToUpperCase() throws Exception { 959 | assertThat(upperFirst("fred"), is("Fred")); 960 | } 961 | 962 | @Test 963 | public void upperFirst_shouldReturnSameStringIfFirstCharIsUpperCase() throws Exception { 964 | assertThat(upperFirst("FRED"), is("FRED")); 965 | } 966 | 967 | @Test 968 | public void trimStart_shouldRemoveAllWhitespaceAtStart() throws Exception { 969 | assertThat(trimStart(" abc "), is(Optional.of("abc "))); 970 | assertThat(trimStart("abc "), is(Optional.of("abc "))); 971 | assertThat(trimStart("abc"), is(Optional.of("abc"))); 972 | assertThat(trimStart(""), is(Optional.empty())); 973 | assertThat(trimStart(null), is(Optional.empty())); 974 | } 975 | 976 | @Test 977 | public void trimStart_shouldRemoveSpecialCharactersAtStart() throws Exception { 978 | assertThat(trimStart("-_-abc-_-", "_", "-"), is(Optional.of("abc-_-"))); 979 | assertThat(trimStart("-_-!abc-_-", "_", "-", "!"), is(Optional.of("abc-_-"))); 980 | assertThat(trimStart("-_-#abc-_-", "_", "-", "!", "#"), is(Optional.of("abc-_-"))); 981 | } 982 | 983 | @Test 984 | public void trimEnd_shouldRemoveAllTrailingWhitespace() throws Exception { 985 | assertThat(trimEnd(" abc "), is(Optional.of(" abc"))); 986 | assertThat(trimEnd("abc "), is(Optional.of("abc"))); 987 | assertThat(trimEnd("abc"), is(Optional.of("abc"))); 988 | assertThat(trimEnd(""), is(Optional.empty())); 989 | assertThat(trimEnd(null), is(Optional.empty())); 990 | } 991 | 992 | @Test 993 | public void trimEnd_shouldRemoveAllTrailingSpecialCharacters() throws Exception { 994 | assertThat(trimEnd("-_-abc-_-", "_", "-"), is(Optional.of("-_-abc"))); 995 | assertThat(trimEnd("-_-abc!-_-", "_", "-", "!"), is(Optional.of("-_-abc"))); 996 | assertThat(trimEnd("-_-abc#-_-", "_", "-", "!", "#"), is(Optional.of("-_-abc"))); 997 | } 998 | 999 | 1000 | @Test 1001 | public void charsCount_shouldReturnEmptyWhenInputStringIsNull() { 1002 | assertThat(charsCount(null), equalTo(Collections.emptyMap())); 1003 | } 1004 | 1005 | @Test 1006 | public void charsCount_shouldReturnEmptyWhenInputStringIsEmpty() { 1007 | assertThat(charsCount(""), equalTo(Collections.emptyMap())); 1008 | } 1009 | 1010 | @Test 1011 | public void charsCount_shouldReturnCharsCountWhenInputIsASimpleString() { 1012 | Map expectedOutput = new HashMap() {{ 1013 | put('a', 1L); 1014 | put('b', 1L); 1015 | put('c', 1L); 1016 | }}; 1017 | 1018 | assertThat(charsCount("abc"), equalTo(expectedOutput)); 1019 | } 1020 | 1021 | @Test 1022 | public void charsCount_shouldReturnCharsCountWhenInputIsAComplexString() { 1023 | Map expectedOutput = new HashMap() {{ 1024 | put('a', 1L); 1025 | put('b', 2L); 1026 | put('c', 3L); 1027 | 1028 | put('A', 1L); 1029 | put('B', 2L); 1030 | put('C', 3L); 1031 | put('-', 10L); 1032 | }}; 1033 | 1034 | assertThat(charsCount("-----abbcccCCCBBA-----"), equalTo(expectedOutput)); 1035 | } 1036 | 1037 | @Test 1038 | public void isBlank_shouldReturnTrueIfNull() { 1039 | assertTrue(isBlank(null)); 1040 | } 1041 | 1042 | @Test 1043 | public void isBlank_shouldReturnTrueIfEmpty() { 1044 | assertTrue(isBlank("")); 1045 | } 1046 | 1047 | @Test 1048 | public void isBlank_shouldReturnFalseIfNotEmpty() { 1049 | assertFalse(isBlank("ac")); 1050 | } 1051 | 1052 | @Test 1053 | public void underscored_shouldReturnUnderscoredString() { 1054 | assertThat(underscored("MozTransform"), equalTo("moz_transform")); 1055 | } 1056 | 1057 | @Test 1058 | public void underscored_shouldReturnEmptyStringIfEmptyStringPassedIn() { 1059 | assertThat(underscored(""), equalTo("")); 1060 | } 1061 | 1062 | @Test 1063 | public void underscored_shouldReturnNullIfNullPassedIn() { 1064 | assertThat(underscored(null), equalTo("")); 1065 | } 1066 | 1067 | @Test 1068 | public void underscored_shouldUnderscoreInputString() throws Exception { 1069 | // assertThat(underscored("foo-bar-baz"), equalTo("foo_bar_baz")); 1070 | assertThat(underscored("fooBarBaz"), equalTo("foo_bar_baz")); 1071 | // assertThat(underscored("FooBarBaz"), equalTo("foo_bar_baz")); 1072 | // assertThat(underscored(" foo bar baz "), equalTo("foo_bar_baz")); 1073 | } 1074 | 1075 | @Test 1076 | public void zip_shouldReturnEmptyList_whenNullOrEmptyIsPassedIn() { 1077 | assertThat(zip("a", null), is(empty())); 1078 | assertThat(zip("", "a"), is(empty())); 1079 | } 1080 | 1081 | @Test 1082 | public void zip_shouldReturnListOfOneElement_forSimplestValidInput() { 1083 | assertThat(zip("a", "b"), equalTo(asList("ab"))); 1084 | } 1085 | 1086 | @Test 1087 | public void zip_shouldReturnExpectedListOfPairs_whenBothInputsHaveSameSize() { 1088 | assertThat(zip("abc", "def"), equalTo(asList("ad", "be", "cf"))); 1089 | assertThat(zip("ABC", "DEF"), equalTo(asList("AD", "BE", "CF"))); 1090 | } 1091 | 1092 | @Test 1093 | public void zip_shouldReturnExpectedListOfPairs_whenFirstInputIsBiggerThanSecond() { 1094 | assertThat(zip("abc", "d"), equalTo(asList("ad"))); 1095 | assertThat(zip("ABCDE", "FGH"), equalTo(asList("AF", "BG", "CH"))); 1096 | } 1097 | 1098 | @Test 1099 | public void zip_shouldReturnExpectedListOfPairs_whenSecondInputIsBiggerThanFirst() { 1100 | assertThat(zip("d", "abc"), equalTo(asList("da"))); 1101 | assertThat(zip("FGH", "ABCDE"), equalTo(asList("FA", "GB", "HC"))); 1102 | } 1103 | 1104 | @Test 1105 | public void zip_shouldReturnExpectedListOfTriplets_whenThreeInputs() { 1106 | assertThat(zip("abc", "def", "ghi"), equalTo(asList("adg", "beh", "cfi"))); 1107 | } 1108 | 1109 | @Test 1110 | public void zip_shouldReturnExpectedListOfTuples_whenMoreThanThreeInputs() { 1111 | assertThat(zip("abc", "def", "ghi", "123"), equalTo(asList("adg1", "beh2", "cfi3"))); 1112 | } 1113 | 1114 | @Test 1115 | public void zip_shouldReturnEmptyList_whenNotEnoughInputs() { 1116 | assertThat(zip(), is(empty())); 1117 | } 1118 | 1119 | @Test 1120 | public void zip_shouldReturnInputInListForm_whenOnlyOneInput() { 1121 | assertThat(zip("zip"), is(equalTo(asList("z", "i", "p")))); 1122 | assertThat(zip("z"), is(equalTo(singletonList("z")))); 1123 | } 1124 | 1125 | @Test 1126 | public void lines_shouldReturnEmptyArrayWhenInputIsNull() throws Exception { 1127 | assertThat(lines(null), emptyArray()); 1128 | } 1129 | 1130 | @Test 1131 | public void lines_shouldReturnArrayWithOneEmptyElementWhenInputIsEmptyString() throws Exception { 1132 | assertThat(lines(""), arrayWithSize(1)); 1133 | assertThat(lines(""), hasItemInArray("")); 1134 | } 1135 | 1136 | @Test 1137 | public void lines_shouldSplitToLines() throws Exception { 1138 | assertThat(lines("Hello\r\nWorld").length, equalTo(2)); 1139 | assertThat(lines("Hello\rWorld").length, equalTo(2)); 1140 | assertThat(lines("Hello World").length, equalTo(1)); 1141 | assertThat(lines("\r\n\n\r ").length, equalTo(4)); 1142 | assertThat(lines("Hello\r\r\nWorld").length, equalTo(3)); 1143 | assertThat(lines("Hello\r\rWorld").length, equalTo(3)); 1144 | } 1145 | 1146 | @Test 1147 | public void humanize_shouldHumanizeStrings() throws Exception { 1148 | assertThat(humanize("the_humanize_method"), equalTo("The humanize method")); 1149 | assertThat(humanize("ThehumanizeMethod"), equalTo("Thehumanize method")); 1150 | assertThat(humanize("ThehumanizeMethod"), equalTo("Thehumanize method")); 1151 | assertThat(humanize("the humanize method"), equalTo("The humanize method")); 1152 | assertThat(humanize("the humanize_id method_id"), equalTo("The humanize id method id")); 1153 | assertThat(humanize("the humanize method "), equalTo("The humanize method")); 1154 | assertThat(humanize(" capitalize dash-CamelCase_underscore trim "), equalTo("Capitalize dash camel case underscore trim")); 1155 | assertThat(humanize(""), equalTo("")); 1156 | assertThat(humanize(null), equalTo("")); 1157 | } 1158 | 1159 | @Test 1160 | public void dasherize_shouldDasherizeInputString() throws Exception { 1161 | assertThat(dasherize("the_dasherize_string_method"), equalTo("the-dasherize-string-method")); 1162 | assertThat(dasherize("TheDasherizeStringMethod"), equalTo("the-dasherize-string-method")); 1163 | assertThat(dasherize("thisIsATest"), equalTo("this-is-a-test")); 1164 | assertThat(dasherize("this Is A Test"), equalTo("this-is-a-test")); 1165 | assertThat(dasherize("thisIsATest123"), equalTo("this-is-a-test123")); 1166 | assertThat(dasherize("123thisIsATest"), equalTo("123this-is-a-test")); 1167 | assertThat(dasherize("the dasherize string method"), equalTo("the-dasherize-string-method")); 1168 | assertThat(dasherize("the dasherize string method "), equalTo("the-dasherize-string-method")); 1169 | assertThat(dasherize("input with a-dash"), equalTo("input-with-a-dash")); 1170 | assertThat(dasherize(""), equalTo("")); 1171 | assertThat(dasherize(null), equalTo("")); 1172 | } 1173 | 1174 | @Test 1175 | public void swapCase_shouldSwapCaseOfCharacters() throws Exception { 1176 | assertThat(swapCase("AaBbCcDdEe"), equalTo("aAbBcCdDeE")); 1177 | assertThat(swapCase("Hello World"), equalTo("hELLO wORLD")); 1178 | assertThat(swapCase(""), equalTo("")); 1179 | assertThat(swapCase(null), equalTo("")); 1180 | } 1181 | 1182 | @Test 1183 | public void chop_shouldChopStringByStep() throws Exception { 1184 | assertThat(chop(null, 2).length, equalTo(0)); 1185 | assertThat(chop("whitespace", 2).length, equalTo(5)); 1186 | assertThat(chop("whitespace", 3).length, equalTo(4)); 1187 | assertThat(chop("whitespace", 0)[0].length(), equalTo(10)); 1188 | } 1189 | 1190 | @Test 1191 | public void formatNumber_shouldFormatNumberWithCommaDelimiter() throws Exception { 1192 | assertThat(formatNumber(1000), equalTo("1,000")); 1193 | assertThat(formatNumber(100000), equalTo("100,000")); 1194 | assertThat(formatNumber(10000000), equalTo("10,000,000")); 1195 | assertThat(formatNumber(100000000), equalTo("100,000,000")); 1196 | } 1197 | 1198 | @Test(expected = IllegalArgumentException.class) 1199 | public void startCase_shouldThrowException() throws Exception { 1200 | startCase(null); 1201 | } 1202 | 1203 | @Test 1204 | public void startCase_shouldStartCaseInputString() throws Exception { 1205 | assertThat(startCase(""), equalTo("")); 1206 | assertThat(startCase("ALL CAPS"), equalTo("All Caps")); 1207 | assertThat(startCase("camelCase"), equalTo("Camel Case")); 1208 | assertThat(startCase("kebab-case"), equalTo("Kebab Case")); 1209 | assertThat(startCase("Snake_case"), equalTo("Snake Case")); 1210 | assertThat(startCase(" spaces "), equalTo("Spaces")); 1211 | assertThat(startCase("spaces between words"), equalTo("Spaces Between Words")); 1212 | assertThat(startCase("--dashes--"), equalTo("Dashes")); 1213 | assertThat(startCase("dashes----between----words"), equalTo("Dashes Between Words")); 1214 | } 1215 | 1216 | @Test(expected = IllegalArgumentException.class) 1217 | public void escapeRegExp_shouldThrowException() throws Exception { 1218 | escapeRegExp(null); 1219 | } 1220 | 1221 | @Test 1222 | public void escapeRegExp_shouldEscapeRegExp() throws Exception { 1223 | assertThat(escapeRegExp("\\"), equalTo("\\\\")); 1224 | assertThat(escapeRegExp("^"), equalTo("\\^")); 1225 | assertThat(escapeRegExp("$"), equalTo("\\$")); 1226 | assertThat(escapeRegExp("*"), equalTo("\\*")); 1227 | assertThat(escapeRegExp("+"), equalTo("\\+")); 1228 | assertThat(escapeRegExp("-"), equalTo("\\-")); 1229 | assertThat(escapeRegExp("?"), equalTo("\\?")); 1230 | assertThat(escapeRegExp("."), equalTo("\\.")); 1231 | assertThat(escapeRegExp("|"), equalTo("\\|")); 1232 | assertThat(escapeRegExp("("), equalTo("\\(")); 1233 | assertThat(escapeRegExp(")"), equalTo("\\)")); 1234 | assertThat(escapeRegExp("{"), equalTo("\\{")); 1235 | assertThat(escapeRegExp("}"), equalTo("\\}")); 1236 | assertThat(escapeRegExp("["), equalTo("\\[")); 1237 | assertThat(escapeRegExp("]"), equalTo("\\]")); 1238 | assertThat(escapeRegExp("How much is (2+3)? 5"), equalTo("How much is \\(2\\+3\\)\\? 5")); 1239 | assertThat(escapeRegExp("\\s|_|-|(?<=[a-z])(?=[A-Z])"), equalTo("\\\\s\\|_\\|\\-\\|\\(\\?<=\\[a\\-z\\]\\)\\(\\?=\\[A\\-Z\\]\\)")); 1240 | } 1241 | } 1242 | --------------------------------------------------------------------------------