diff --git a/core-java-modules/core-java-string-algorithms-3/pom.xml b/core-java-modules/core-java-string-algorithms-3/pom.xml
index 536175acc2..507e830e8a 100644
--- a/core-java-modules/core-java-string-algorithms-3/pom.xml
+++ b/core-java-modules/core-java-string-algorithms-3/pom.xml
@@ -28,6 +28,11 @@
emoji-java
${emoji-java.version}
+
+ org.apache.commons
+ commons-text
+ ${apache-commons-text.version}
+
@@ -58,6 +63,7 @@
1.7
3.12.0
5.1.1
+ 1.10.0
\ No newline at end of file
diff --git a/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java b/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java
new file mode 100644
index 0000000000..7400745b2f
--- /dev/null
+++ b/core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java
@@ -0,0 +1,28 @@
+package com.baeldung.wrappingcharacterwise;
+
+import java.lang.IllegalArgumentException;
+import java.lang.String;
+import java.lang.StringBuilder;
+
+public class Wrapper {
+
+ public String wrapStringCharacterWise(String input, int n) {
+ StringBuilder stringBuilder = new StringBuilder(input);
+ int index = 0;
+ while(stringBuilder.length() > index + n) {
+ int lastLineReturn = stringBuilder.lastIndexOf("\n", index + n);
+ if (lastLineReturn > index) {
+ index = lastLineReturn;
+ } else {
+ index = stringBuilder.lastIndexOf(" ", index + n);
+ if (index == -1) {
+ throw new IllegalArgumentException("impossible to slice " + stringBuilder.substring(0, n));
+ }
+ stringBuilder.replace(index, index + 1, "\n");
+ index++;
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+}
diff --git a/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java
new file mode 100644
index 0000000000..8dcc323f7b
--- /dev/null
+++ b/core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.wrappingcharacterwise;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.commons.text.WordUtils;
+import org.junit.jupiter.api.Test;
+
+public class WrapperUnitTest {
+
+ Wrapper wrapper = new Wrapper();
+ String lineSeparator = System.lineSeparator();
+
+ @Test
+ void givenStringWithLessThanNCharacters_whenWrapStringCharacterWise_thenUnchanged() {
+ String input = "short sentence";
+ assertEquals(input, wrapper.wrapStringCharacterWise(input, 20));
+ }
+
+ @Test
+ void givenStringWithMoreThanNCharacters_whenWrapStringCharacterWise_thenCorrectlyWrapped() {
+ String input = "Baeldung is a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung is a\npopular website that\nprovides in-depth\ntutorials and\narticles on various\nprogramming and\nsoftware development\ntopics, primarily\nfocused on Java and\nrelated\ntechnologies.", wrapper.wrapStringCharacterWise(input, 20));
+ }
+
+ @Test
+ void givenStringWithATooLongWord_whenWrapStringCharacterWise_thenThrows() {
+ String input = "The word straightforward has more than 10 characters";
+ assertThrows(IllegalArgumentException.class, () -> wrapper.wrapStringCharacterWise(input, 10));
+ }
+
+ @Test
+ void givenStringWithLineReturns_whenWrapStringCharacterWise_thenWrappedAccordingly() {
+ String input = "Baeldung\nis a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung\nis a popular\nwebsite that\nprovides in-depth\ntutorials and\narticles on various\nprogramming and\nsoftware development\ntopics, primarily\nfocused on Java and\nrelated\ntechnologies.", wrapper.wrapStringCharacterWise(input, 20));
+ }
+
+ @Test
+ void givenStringWithLessThanNCharacters_whenWrap_thenUnchanged() {
+ String input = "short sentence";
+ assertEquals(input, WordUtils.wrap(input, 20));
+ }
+
+ @Test
+ void givenStringWithMoreThanNCharacters_whenWrap_thenCorrectlyWrapped() {
+ String input = "Baeldung is a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung is a" + lineSeparator + "popular website that" + lineSeparator + "provides in-depth" + lineSeparator + "tutorials and" + lineSeparator + "articles on various" + lineSeparator + "programming and" + lineSeparator + "software development" + lineSeparator + "topics, primarily" + lineSeparator + "focused on Java and" + lineSeparator + "related" + lineSeparator + "technologies.", WordUtils.wrap(input, 20));
+ }
+
+ @Test
+ void givenStringWithATooLongWord_whenWrap_thenLongWordIsNotWrapped() {
+ String input = "The word straightforward has more than 10 characters";
+ assertEquals("The word" + lineSeparator + "straightforward" + lineSeparator + "has more" + lineSeparator + "than 10" + lineSeparator + "characters", WordUtils.wrap(input, 10));
+ }
+
+ @Test
+ void givenStringWithLineReturns_whenWrap_thenWrappedLikeThereWasNone() {
+ String input = "Baeldung" + lineSeparator + "is a popular website that provides in-depth tutorials and articles on various programming and software development topics, primarily focused on Java and related technologies.";
+ assertEquals("Baeldung" + lineSeparator + "is a" + lineSeparator + "popular website that" + lineSeparator + "provides in-depth" + lineSeparator + "tutorials and" + lineSeparator + "articles on various" + lineSeparator + "programming and" + lineSeparator + "software development" + lineSeparator + "topics, primarily" + lineSeparator + "focused on Java and" + lineSeparator + "related" + lineSeparator + "technologies.", WordUtils.wrap(input, 20));
+ }
+
+}