8017231: Add StringJoiner.merge
authoralanb
Thu, 04 Jul 2013 20:00:20 +0100
changeset 18778 7214a903b084
parent 18777 cb1cc62972b8
child 18779 c521f8c13c53
8017231: Add StringJoiner.merge Reviewed-by: psandoz, alanb Contributed-by: brian.goetz@oracle.com, henry.jen@oracle.com
jdk/src/share/classes/java/util/StringJoiner.java
jdk/test/java/util/StringJoiner/MergeTest.java
jdk/test/java/util/StringJoiner/StringJoinerTest.java
--- a/jdk/src/share/classes/java/util/StringJoiner.java	Thu Jul 04 14:38:44 2013 +0100
+++ b/jdk/src/share/classes/java/util/StringJoiner.java	Thu Jul 04 20:00:20 2013 +0100
@@ -114,8 +114,9 @@
      * @throws NullPointerException if {@code prefix}, {@code delimiter}, or
      *         {@code suffix} is {@code null}
      */
-    public StringJoiner(CharSequence delimiter, CharSequence prefix,
-            CharSequence suffix) {
+    public StringJoiner(CharSequence delimiter,
+                        CharSequence prefix,
+                        CharSequence suffix) {
         Objects.requireNonNull(prefix, "The prefix must not be null");
         Objects.requireNonNull(delimiter, "The delimiter must not be null");
         Objects.requireNonNull(suffix, "The suffix must not be null");
@@ -172,7 +173,7 @@
     }
 
     /**
-     * Add the a copy of the supplied {@code CharSequence} value as the next
+     * Adds a copy of the given {@code CharSequence} value as the next
      * element of the {@code StringJoiner} value. If {@code newElement} is
      * {@code null}, then {@code "null"} is added.
      *
@@ -184,6 +185,36 @@
         return this;
     }
 
+    /**
+     * Adds the contents of the given {@code StringJoiner} without prefix and
+     * suffix as the next element if it is non-empty. If the given {@code
+     * StringJoiner} is empty, the call has no effect.
+     *
+     * <p>A {@code StringJoiner} is empty if {@link #add(CharSequence) add()}
+     * has never been called, and if {@code merge()} has never been called
+     * with a non-empty {@code StringJoiner} argument.
+     *
+     * <p>If the other {@code StringJoiner} is using a different delimiter,
+     * then elements from the other {@code StringJoiner} are concatenated with
+     * that delimiter and the result is appended to this {@code StringJoiner}
+     * as a single element.
+     *
+     * @param other The {@code StringJoiner} whose contents should be merged
+     *              into this one
+     * @throws NullPointerException if the other {@code StringJoiner} is null
+     */
+    public StringJoiner merge(StringJoiner other) {
+        Objects.requireNonNull(other);
+        if (other.value != null) {
+            StringBuilder builder = prepareBuilder();
+            StringBuilder otherBuilder = other.value;
+            if (other.prefix.length() < otherBuilder.length()) {
+                builder.append(otherBuilder, other.prefix.length(), otherBuilder.length());
+            }
+        }
+        return this;
+    }
+
     private StringBuilder prepareBuilder() {
         if (value != null) {
             value.append(delimiter);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/StringJoiner/MergeTest.java	Thu Jul 04 20:00:20 2013 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8017231
+ * @summary test  StringJoiner::merge
+ * @run testng MergeTest
+ */
+
+import java.util.StringJoiner;
+import java.util.stream.Stream;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+@Test
+public class MergeTest {
+    public void testNull() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        try {
+            sj.merge(null);
+            fail("Should throw NullPointerException!");
+        } catch (NullPointerException npe) {
+            // expected
+        }
+    }
+
+    public void testSimple() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        StringJoiner other = new StringJoiner(",", "[", "]");
+        Stream.of("a", "b", "c").forEachOrdered(sj::add);
+        Stream.of("d", "e", "f").forEachOrdered(other::add);
+
+        sj.merge(other);
+        assertEquals(sj.toString(), "{a,b,c,d,e,f}");
+    }
+
+    public void testEmptyOther() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        StringJoiner other = new StringJoiner(",", "[", "]");
+        Stream.of("a", "b", "c").forEachOrdered(sj::add);
+
+        sj.merge(other);
+        assertEquals(sj.toString(), "{a,b,c}");
+
+        other.setEmptyValue("EMPTY");
+        sj.merge(other);
+        assertEquals(sj.toString(), "{a,b,c}");
+    }
+
+    public void testEmptyThis() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        StringJoiner other = new StringJoiner(":", "[", "]");
+        Stream.of("d", "e", "f").forEachOrdered(other::add);
+
+        sj.merge(other);
+        assertEquals(sj.toString(), "{d:e:f}");
+
+        sj = new StringJoiner(",", "{", "}").setEmptyValue("EMPTY");
+        assertEquals(sj.toString(), "EMPTY");
+        sj.merge(other);
+        assertEquals(sj.toString(), "{d:e:f}");
+    }
+
+    public void testEmptyBoth() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        StringJoiner other = new StringJoiner(":", "[", "]");
+
+        sj.merge(other);
+        assertEquals(sj.toString(), "{}");
+
+        other.setEmptyValue("NOTHING");
+        sj.merge(other);
+        assertEquals(sj.toString(), "{}");
+
+        sj = new StringJoiner(",", "{", "}").setEmptyValue("EMPTY");
+        assertEquals(sj.toString(), "EMPTY");
+        sj.merge(other);
+        assertEquals(sj.toString(), "EMPTY");
+    }
+
+    public void testCascadeEmpty() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        StringJoiner o1 = new StringJoiner(":", "[", "]").setEmptyValue("Empty1");
+        StringJoiner o2 = new StringJoiner(",", "<", ">").setEmptyValue("Empty2");
+
+        o1.merge(o2);
+        assertEquals(o1.toString(), "Empty1");
+
+        sj.merge(o1);
+        assertEquals(sj.toString(), "{}");
+    }
+
+    public void testDelimiter() {
+        StringJoiner sj = new StringJoiner(",", "{", "}");
+        StringJoiner other = new StringJoiner(":", "[", "]");
+        Stream.of("a", "b", "c").forEachOrdered(sj::add);
+        Stream.of("d", "e", "f").forEachOrdered(other::add);
+
+        sj.merge(other);
+        assertEquals(sj.toString(), "{a,b,c,d:e:f}");
+    }
+}
\ No newline at end of file
--- a/jdk/test/java/util/StringJoiner/StringJoinerTest.java	Thu Jul 04 14:38:44 2013 +0100
+++ b/jdk/test/java/util/StringJoiner/StringJoinerTest.java	Thu Jul 04 20:00:20 2013 +0100
@@ -27,6 +27,7 @@
  * @run testng StringJoinerTest
  * @author Jim Gish
  */
+import java.util.ArrayList;
 import java.util.StringJoiner;
 import org.testng.annotations.Test;
 import static org.testng.Assert.assertEquals;
@@ -44,7 +45,6 @@
     private static final String FIVE = "Five";
     private static final String DASH = "-";
 
-    /* Uncomment when we have streams
     public void addAddAll() {
         StringJoiner sj = new StringJoiner(DASH, "{", "}");
         sj.add(ONE);
@@ -52,7 +52,7 @@
         ArrayList<String> nextOne = new ArrayList<>();
         nextOne.add(TWO);
         nextOne.add(THREE);
-        nextOne.stream().forEach(sj::add);
+        nextOne.stream().forEachOrdered(sj::add);
 
         String expected = "{"+ONE+DASH+TWO+DASH+THREE+"}";
         assertEquals(sj.toString(), expected);
@@ -64,7 +64,7 @@
         ArrayList<String> firstOne = new ArrayList<>();
         firstOne.add(ONE);
         firstOne.add(TWO);
-        firstOne.stream().forEach(sj::add);
+        firstOne.stream().forEachOrdered(sj::add);
 
         sj.add(THREE);
 
@@ -79,29 +79,17 @@
         firstOne.add(ONE);
         firstOne.add(TWO);
         firstOne.add(THREE);
-        firstOne.stream().forEach(sj::add);
+        firstOne.stream().forEachOrdered(sj::add);
 
         ArrayList<String> nextOne = new ArrayList<>();
         nextOne.add(FOUR);
         nextOne.add(FIVE);
-        nextOne.stream().forEach(sj::add);
+        nextOne.stream().forEachOrdered(sj::add);
 
         String expected = "{"+ONE+DASH+TWO+DASH+THREE+DASH+FOUR+DASH+FIVE+"}";
         assertEquals(sj.toString(), expected);
     }
 
-    public void testInto() {
-        ArrayList<String> list = new ArrayList<>();
-        list.add(ONE);
-        list.add(TWO);
-        list.add(THREE);
-
-        StringJoiner target = new StringJoiner(",", "{", "}");
-        assertEquals(target.toString(), "{" + ONE + "," + TWO + "," + THREE +
-            "}");
-    }
-    */
-
     public void addCharSequence() {
         StringJoiner sj = new StringJoiner(",");
         CharSequence cs_one = ONE;