<action issue="LANG-835" type="add">StrBuilder should support StringBuilder as an input parameter</action>

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1413671 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6895d57..4263d9a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -22,6 +22,7 @@
   <body>
 
   <release version="3.2" date="TBA" description="Next release">
+    <action issue="LANG-835" type="add">StrBuilder should support StringBuilder as an input parameter</action>
     <action issue="LANG-858" type="fix">StringEscapeUtils.escapeJava() and escapeEcmaScript() do not output the escaped surrogate pairs that are Java parsable</action>
     <action issue="LANG-857" type="add">StringIndexOutOfBoundsException in CharSequenceTranslator</action>
     <action issue="LANG-856" type="add">Code refactoring in NumberUtils</action>
diff --git a/src/main/java/org/apache/commons/lang3/text/StrBuilder.java b/src/main/java/org/apache/commons/lang3/text/StrBuilder.java
index 86752b0..ab25d48 100644
--- a/src/main/java/org/apache/commons/lang3/text/StrBuilder.java
+++ b/src/main/java/org/apache/commons/lang3/text/StrBuilder.java
@@ -498,7 +498,7 @@
         } 
         return append(seq.toString(), startIndex, length);
     }
-
+    
     /**
      * Appends a string to this string builder.
      * Appending null will call {@link #appendNull()}.
@@ -519,6 +519,7 @@
         }
         return this;
     }
+   
 
     /**
      * Appends part of a string to this string builder.
@@ -611,6 +612,57 @@
     }
 
     /**
+     * Appends a StringBuilder to this string builder.
+     * Appending null will call {@link #appendNull()}.
+     *
+     * @param str the StringBuilder to append
+     * @return this, to enable chaining
+     * @since 3.2
+     */
+    public StrBuilder append(StringBuilder str) {
+        if (str == null) {
+            return appendNull();
+        }
+        int strLen = str.length();
+        if (strLen > 0) {
+            int len = length();
+            ensureCapacity(len + strLen);
+            str.getChars(0, strLen, buffer, len);
+            size += strLen;
+        }
+        return this;
+    }
+    
+    /**
+     * Appends part of a StringBuilder to this string builder.
+     * Appending null will call {@link #appendNull()}.
+     *
+     * @param str the StringBuilder to append
+     * @param startIndex the start index, inclusive, must be valid
+     * @param length the length to append, must be valid
+     * @return this, to enable chaining
+     * @since 3.2
+     */
+    public StrBuilder append(StringBuilder str, int startIndex, int length) {
+        if (str == null) {
+            return appendNull();
+        }
+        if (startIndex < 0 || startIndex > str.length()) {
+            throw new StringIndexOutOfBoundsException("startIndex must be valid");
+        }
+        if (length < 0 || (startIndex + length) > str.length()) {
+            throw new StringIndexOutOfBoundsException("length must be valid");
+        }
+        if (length > 0) {
+            int len = length();
+            ensureCapacity(len + length);
+            str.getChars(startIndex, startIndex + length, buffer, len);
+            size += length;
+        }
+        return this;
+    }
+
+    /**
      * Appends another string builder to this string builder.
      * Appending null will call {@link #appendNull()}.
      *
@@ -852,6 +904,32 @@
     }
 
     /**
+     * Appends a string builder followed by a new line to this string builder.
+     * Appending null will call {@link #appendNull()}.
+     *
+     * @param str  the string builder to append
+     * @return this, to enable chaining
+     * @since 3.2
+     */
+    public StrBuilder appendln(StringBuilder str) {
+        return append(str).appendNewLine();
+    }
+
+    /**
+     * Appends part of a string builder followed by a new line to this string builder.
+     * Appending null will call {@link #appendNull()}.
+     *
+     * @param str  the string builder to append
+     * @param startIndex  the start index, inclusive, must be valid
+     * @param length  the length to append, must be valid
+     * @return this, to enable chaining
+     * @since 3.2
+     */
+    public StrBuilder appendln(StringBuilder str, int startIndex, int length) {
+        return append(str, startIndex, length).appendNewLine();
+    }
+
+    /**
      * Appends part of a string buffer followed by a new line to this string builder.
      * Appending null will call {@link #appendNull()}.
      *
diff --git a/src/test/java/org/apache/commons/lang3/text/StrBuilderAppendInsertTest.java b/src/test/java/org/apache/commons/lang3/text/StrBuilderAppendInsertTest.java
index 98908ae..ef7dd63 100644
--- a/src/test/java/org/apache/commons/lang3/text/StrBuilderAppendInsertTest.java
+++ b/src/test/java/org/apache/commons/lang3/text/StrBuilderAppendInsertTest.java
@@ -116,6 +116,24 @@
         sb.append(new StringBuilder("bld")); // Check it supports StringBuilder
         assertEquals("foobazyesSeqbld", sb.toString());
     }
+    
+    //-----------------------------------------------------------------------
+    @Test
+    public void testAppend_StringBuilder() {
+        StrBuilder sb = new StrBuilder();
+        sb.setNullText("NULL").append((String) null);
+        assertEquals("NULL", sb.toString());
+
+        sb = new StrBuilder();
+        sb.append(new StringBuilder("foo"));
+        assertEquals("foo", sb.toString());
+
+        sb.append(new StringBuilder(""));
+        assertEquals("foo", sb.toString());
+
+        sb.append(new StringBuilder("bar"));
+        assertEquals("foobar", sb.toString());
+    }
 
     //-----------------------------------------------------------------------
     @Test
@@ -197,6 +215,69 @@
         sb.append( (CharSequence)"abcbardef", 4, 3);
         assertEquals("foobarard", sb.toString());
     }
+    
+    //-----------------------------------------------------------------------
+    @Test
+    public void testAppend_StringBuilder_int_int() {
+        StrBuilder sb = new StrBuilder();
+        sb.setNullText("NULL").append((String) null, 0, 1);
+        assertEquals("NULL", sb.toString());
+
+        sb = new StrBuilder();
+        sb.append(new StringBuilder("foo"), 0, 3);
+        assertEquals("foo", sb.toString());
+
+        try {
+            sb.append(new StringBuilder("bar"), -1, 1);
+            fail("append(StringBuilder, -1,) expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sb.append(new StringBuilder("bar"), 3, 1);
+            fail("append(StringBuilder, 3,) expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sb.append(new StringBuilder("bar"), 1, -1);
+            fail("append(StringBuilder,, -1) expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sb.append(new StringBuilder("bar"), 1, 3);
+            fail("append(StringBuilder, 1, 3) expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sb.append(new StringBuilder("bar"), -1, 3);
+            fail("append(StringBuilder, -1, 3) expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sb.append(new StringBuilder("bar"), 4, 0);
+            fail("append(StringBuilder, 4, 0) expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        sb.append(new StringBuilder("bar"), 3, 0);
+        assertEquals("foo", sb.toString());
+
+        sb.append(new StringBuilder("abcbardef"), 3, 3);
+        assertEquals("foobar", sb.toString());
+
+        sb.append( new StringBuilder("abcbardef"), 4, 3);
+        assertEquals("foobarard", sb.toString());
+    }
 
     //-----------------------------------------------------------------------
     @Test
@@ -564,6 +645,28 @@
 
     //-----------------------------------------------------------------------
     @Test
+    public void testAppendln_StringBuilder() {
+        final int[] count = new int[2];
+        StrBuilder sb = new StrBuilder() {
+            @Override
+            public StrBuilder append(StringBuilder str) {
+                count[0]++;
+                return super.append(str);
+            }
+            @Override
+            public StrBuilder appendNewLine() {
+                count[1]++;
+                return super.appendNewLine();
+            }
+        };
+        sb.appendln(new StringBuilder("foo"));
+        assertEquals("foo" + SEP, sb.toString());
+        assertEquals(1, count[0]);
+        assertEquals(1, count[1]);
+    }
+
+    //-----------------------------------------------------------------------
+    @Test
     public void testAppendln_StringBuffer_int_int() {
         final int[] count = new int[2];
         StrBuilder sb = new StrBuilder() {
@@ -586,6 +689,28 @@
 
     //-----------------------------------------------------------------------
     @Test
+    public void testAppendln_StringBuilder_int_int() {
+        final int[] count = new int[2];
+        StrBuilder sb = new StrBuilder() {
+            @Override
+            public StrBuilder append(StringBuilder str, int startIndex, int length) {
+                count[0]++;
+                return super.append(str, startIndex, length);
+            }
+            @Override
+            public StrBuilder appendNewLine() {
+                count[1]++;
+                return super.appendNewLine();
+            }
+        };
+        sb.appendln(new StringBuilder("foo"), 0, 3);
+        assertEquals("foo" + SEP, sb.toString());
+        assertEquals(1, count[0]);
+        assertEquals(1, count[1]);
+    }
+
+    //-----------------------------------------------------------------------
+    @Test
     public void testAppendln_StrBuilder() {
         final int[] count = new int[2];
         StrBuilder sb = new StrBuilder() {