From 0bf14c03f5b377eb5663a6e58d2ba143fc6ae047 Mon Sep 17 00:00:00 2001
From: Thibault Faure <thibault.faure.pro@gmail.com>
Date: Sat, 2 Sep 2023 17:20:39 +0200
Subject: [PATCH] BAEL-6591 Code for the Wrapping a String After a Number of
 Characters World-Wise in Java article

---
 .../core-java-string-algorithms-3/pom.xml     |  6 ++
 .../wrappingcharacterwise/Wrapper.java        | 28 +++++++++
 .../WrapperUnitTest.java                      | 62 +++++++++++++++++++
 3 files changed, 96 insertions(+)
 create mode 100644 core-java-modules/core-java-string-algorithms-3/src/main/java/com/baeldung/wrappingcharacterwise/Wrapper.java
 create mode 100644 core-java-modules/core-java-string-algorithms-3/src/test/java/com/baeldung/wrappingcharacterwise/WrapperUnitTest.java

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 @@
             <artifactId>emoji-java</artifactId>
             <version>${emoji-java.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-text</artifactId>
+            <version>${apache-commons-text.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -58,6 +63,7 @@
         <validator.version>1.7</validator.version>
         <apache-commons-lang3.version>3.12.0</apache-commons-lang3.version>
         <emoji-java.version>5.1.1</emoji-java.version>
+        <apache-commons-text.version>1.10.0</apache-commons-text.version>
     </properties>
 
 </project>
\ 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));
+    }
+
+}