11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.base; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.IOException; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractList; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map.Entry; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.CheckReturnValue; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An object which joins pieces of text (specified as an array, {@link Iterable}, varargs or even a 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link Map}) with a separator. It either appends the results to an {@link Appendable} or returns 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * them as a {@link String}. Example: <pre> {@code 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Joiner joiner = Joiner.on("; ").skipNulls(); 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * . . . 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * return joiner.join("Harry", null, "Ron", "Hermione");}</pre> 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * This returns the string {@code "Harry; Ron; Hermione"}. Note that all input elements are 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * converted to strings using {@link Object#toString()} before being appended. 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>If neither {@link #skipNulls()} nor {@link #useForNull(String)} is specified, the joining 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * methods will throw {@link NullPointerException} if any given element is null. 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning: joiner instances are always immutable</b>; a configuration method such as {@code 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * useForNull} has no effect on the instance it is invoked on! You must store and use the new joiner 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * instance returned by the method. This makes joiners thread-safe, and safe to store as {@code 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * static final} constants. <pre> {@code 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * // Bad! Do not do this! 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Joiner joiner = Joiner.on(','); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * joiner.skipNulls(); // does nothing! 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * return joiner.join("wrong", null, "wrong");}</pre> 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library) 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class Joiner { 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a joiner which automatically places {@code separator} between consecutive elements. 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static Joiner on(String separator) { 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Joiner(separator); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a joiner which automatically places {@code separator} between consecutive elements. 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static Joiner on(char separator) { 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Joiner(String.valueOf(separator)); 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final String separator; 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Joiner(String separator) { 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.separator = checkNotNull(separator); 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Joiner(Joiner prototype) { 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.separator = prototype.separator; 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Deprecated.</b> 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #appendTo(Appendable, Iterator)} by casting {@code parts} to 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator<?>}, or better yet, by implementing only {@code Iterator} and not 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterable}. <b>This method is scheduled for deletion in June 2013.</b> 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final <A extends Appendable, I extends Object & Iterable<?> & Iterator<?>> A 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendTo(A appendable, I parts) throws IOException { 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, (Iterator<?>) parts); 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each of {@code parts}, using the previously configured 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separator between each, to {@code appendable}. 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <A extends Appendable> A appendTo(A appendable, Iterable<?> parts) throws IOException { 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, parts.iterator()); 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each of {@code parts}, using the previously configured 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separator between each, to {@code appendable}. 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException { 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(appendable); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (parts.hasNext()) { 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(toString(parts.next())); 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (parts.hasNext()) { 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(separator); 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(toString(parts.next())); 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendable; 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each of {@code parts}, using the previously configured 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separator between each, to {@code appendable}. 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final <A extends Appendable> A appendTo(A appendable, Object[] parts) throws IOException { 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, Arrays.asList(parts)); 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends to {@code appendable} the string representation of each of the remaining arguments. 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final <A extends Appendable> A appendTo( 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert A appendable, @Nullable Object first, @Nullable Object second, Object... rest) 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throws IOException { 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, iterable(first, second, rest)); 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Deprecated.</b> 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #appendTo(StringBuilder, Iterator)} by casting {@code parts} to 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator<?>}, or better yet, by implementing only {@code Iterator} and not 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterable}. <b>This method is scheduled for deletion in June 2013.</b> 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final <I extends Object & Iterable<?> & Iterator<?>> StringBuilder 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendTo(StringBuilder builder, I parts) { 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, (Iterator<?>) parts); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each of {@code parts}, using the previously configured 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separator between each, to {@code builder}. Identical to {@link #appendTo(Appendable, 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Iterable)}, except that it does not throw {@link IOException}. 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final StringBuilder appendTo(StringBuilder builder, Iterable<?> parts) { 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, parts.iterator()); 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each of {@code parts}, using the previously configured 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separator between each, to {@code builder}. Identical to {@link #appendTo(Appendable, 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Iterable)}, except that it does not throw {@link IOException}. 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) { 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendTo((Appendable) builder, parts); 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IOException impossible) { 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new AssertionError(impossible); 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return builder; 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each of {@code parts}, using the previously configured 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separator between each, to {@code builder}. Identical to {@link #appendTo(Appendable, 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Iterable)}, except that it does not throw {@link IOException}. 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final StringBuilder appendTo(StringBuilder builder, Object[] parts) { 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, Arrays.asList(parts)); 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends to {@code builder} the string representation of each of the remaining arguments. 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Identical to {@link #appendTo(Appendable, Object, Object, Object...)}, except that it does not 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * throw {@link IOException}. 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final StringBuilder appendTo( 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert StringBuilder builder, @Nullable Object first, @Nullable Object second, Object... rest) { 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, iterable(first, second, rest)); 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Deprecated.</b> 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #join(Iterator)} by casting {@code parts} to 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator<?>}, or better yet, by implementing only {@code Iterator} and not 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterable}. <b>This method is scheduled for deletion in June 2013.</b> 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final <I extends Object & Iterable<?> & Iterator<?>> String join(I parts) { 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join((Iterator<?>) parts); 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each of {@code parts}, using the 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * previously configured separator between each. 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final String join(Iterable<?> parts) { 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join(parts.iterator()); 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each of {@code parts}, using the 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * previously configured separator between each. 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final String join(Iterator<?> parts) { 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(new StringBuilder(), parts).toString(); 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each of {@code parts}, using the 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * previously configured separator between each. 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final String join(Object[] parts) { 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join(Arrays.asList(parts)); 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each argument, using the previously 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator between each. 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final String join(@Nullable Object first, @Nullable Object second, Object... rest) { 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join(iterable(first, second, rest)); 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a joiner with the same behavior as this one, except automatically substituting {@code 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * nullText} for any provided null elements. 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Joiner useForNull(final String nullText) { 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(nullText); 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Joiner(this) { 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override CharSequence toString(Object part) { 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (part == null) ? nullText : Joiner.this.toString(part); 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Joiner useForNull(String nullText) { 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(nullText); // weird: just to satisfy NullPointerTester. 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("already specified useForNull"); 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Joiner skipNulls() { 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("already specified useForNull"); 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a joiner with the same behavior as this joiner, except automatically skipping over any 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * provided null elements. 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Joiner skipNulls() { 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Joiner(this) { 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throws IOException { 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(appendable, "appendable"); 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(parts, "parts"); 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (parts.hasNext()) { 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object part = parts.next(); 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (part != null) { 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(Joiner.this.toString(part)); 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert break; 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (parts.hasNext()) { 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object part = parts.next(); 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (part != null) { 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(separator); 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(Joiner.this.toString(part)); 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendable; 3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Joiner useForNull(String nullText) { 3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(nullText); // weird: just to satisfy NullPointerTester. 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("already specified skipNulls"); 3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public MapJoiner withKeyValueSeparator(String kvs) { 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(kvs); // weird: just to satisfy NullPointerTester. 3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("can't use .skipNulls() with maps"); 3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a {@code MapJoiner} using the given key-value separator, and the same configuration as 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * this {@code Joiner} otherwise. 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapJoiner withKeyValueSeparator(String keyValueSeparator) { 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new MapJoiner(this, keyValueSeparator); 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An object that joins map entries in the same manner as {@code Joiner} joins iterables and 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * arrays. Like {@code Joiner}, it is thread-safe and immutable. 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>In addition to operating on {@code Map} instances, {@code MapJoiner} can operate on {@code 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Multimap} entries in two distinct modes: 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul> 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>To output a separate entry for each key-value pair, pass {@code multimap.entries()} to a 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code MapJoiner} method that accepts entries as input, and receive output of the form 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code key1=A&key1=B&key2=C}. 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>To output a single entry for each key, pass {@code multimap.asMap()} to a {@code MapJoiner} 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * method that accepts a map as input, and receive output of the form {@code 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * key1=[A, B]&key2=C}. 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul> 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library) 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final static class MapJoiner { 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final Joiner joiner; 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final String keyValueSeparator; 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private MapJoiner(Joiner joiner, String keyValueSeparator) { 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.joiner = joiner; // only "this" is ever passed, so don't checkNotNull 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.keyValueSeparator = checkNotNull(keyValueSeparator); 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each entry of {@code map}, using the previously 3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator and key-value separator, to {@code appendable}. 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <A extends Appendable> A appendTo(A appendable, Map<?, ?> map) throws IOException { 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, map.entrySet()); 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each entry of {@code map}, using the previously 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator and key-value separator, to {@code builder}. Identical to {@link 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #appendTo(Appendable, Map)}, except that it does not throw {@link IOException}. 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public StringBuilder appendTo(StringBuilder builder, Map<?, ?> map) { 3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, map.entrySet()); 3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each entry of {@code map}, using the 3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * previously configured separator and key-value separator. 3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public String join(Map<?, ?> map) { 3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join(map.entrySet()); 3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Deprecated.</b> 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #appendTo(Appendable, Iterator)} by casting {@code entries} to 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator<? extends Entry<?, ?>>}, or better yet, by implementing only 3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator} and not {@code Iterable}. <b>This method is scheduled for deletion 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in June 2013.</b> 3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <A extends Appendable, 3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert I extends Object & Iterable<? extends Entry<?, ?>> & Iterator<? extends Entry<?, ?>>> 3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert A appendTo(A appendable, I entries) throws IOException { 3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterator<? extends Entry<?, ?>> iterator = entries; 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, iterator); 3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each entry in {@code entries}, using the previously 4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator and key-value separator, to {@code appendable}. 4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <A extends Appendable> A appendTo(A appendable, Iterable<? extends Entry<?, ?>> entries) 4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throws IOException { 4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(appendable, entries.iterator()); 4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each entry in {@code entries}, using the previously 4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator and key-value separator, to {@code appendable}. 4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <A extends Appendable> A appendTo(A appendable, Iterator<? extends Entry<?, ?>> parts) 4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throws IOException { 4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(appendable); 4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (parts.hasNext()) { 4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Entry<?, ?> entry = parts.next(); 4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(joiner.toString(entry.getKey())); 4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(keyValueSeparator); 4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(joiner.toString(entry.getValue())); 4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (parts.hasNext()) { 4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(joiner.separator); 4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Entry<?, ?> e = parts.next(); 4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(joiner.toString(e.getKey())); 4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(keyValueSeparator); 4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendable.append(joiner.toString(e.getValue())); 4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendable; 4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Deprecated.</b> 4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #appendTo(StringBuilder, Iterator)} by casting {@code entries} to 4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator<? extends Entry<?, ?>>}, or better yet, by implementing only 4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator} and not {@code Iterable}. <b>This method is scheduled for deletion 4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in June 2013.</b> 4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <I extends Object & Iterable<? extends Entry<?, ?>> & Iterator<? extends Entry<?, ?>>> 4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert StringBuilder appendTo(StringBuilder builder, I entries) throws IOException { 4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterator<? extends Entry<?, ?>> iterator = entries; 4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, iterator); 4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each entry in {@code entries}, using the previously 4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator and key-value separator, to {@code builder}. Identical to {@link 4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #appendTo(Appendable, Iterable)}, except that it does not throw {@link IOException}. 4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public StringBuilder appendTo(StringBuilder builder, Iterable<? extends Entry<?, ?>> entries) { 4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(builder, entries.iterator()); 4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Appends the string representation of each entry in {@code entries}, using the previously 4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * configured separator and key-value separator, to {@code builder}. Identical to {@link 4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #appendTo(Appendable, Iterable)}, except that it does not throw {@link IOException}. 4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public StringBuilder appendTo(StringBuilder builder, Iterator<? extends Entry<?, ?>> entries) { 4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert appendTo((Appendable) builder, entries); 4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IOException impossible) { 4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new AssertionError(impossible); 4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return builder; 4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Deprecated.</b> 4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #join(Iterator)} by casting {@code entries} to 4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator<? extends Entry<?, ?>>}, or better yet, by implementing only 4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Iterator} and not {@code Iterable}. <b>This method is scheduled for deletion 4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in June 2013.</b> 4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <I extends Object & Iterable<? extends Entry<?, ?>> & Iterator<? extends Entry<?, ?>>> 4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String join(I entries) throws IOException { 4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterator<? extends Entry<?, ?>> iterator = entries; 4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join(iterator); 4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each entry in {@code entries}, using 5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the previously configured separator and key-value separator. 5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public String join(Iterable<? extends Entry<?, ?>> entries) { 5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return join(entries.iterator()); 5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string containing the string representation of each entry in {@code entries}, using 5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the previously configured separator and key-value separator. 5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Beta 5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public String join(Iterator<? extends Entry<?, ?>> entries) { 5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return appendTo(new StringBuilder(), entries).toString(); 5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a map joiner with the same behavior as this one, except automatically substituting 5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code nullText} for any provided null keys or values. 5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @CheckReturnValue 5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapJoiner useForNull(String nullText) { 5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new MapJoiner(joiner.useForNull(nullText), keyValueSeparator); 5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CharSequence toString(Object part) { 5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(part); // checkNotNull for GWT (do not optimize). 5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (part instanceof CharSequence) ? (CharSequence) part : part.toString(); 5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Iterable<Object> iterable( 5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Object first, final Object second, final Object[] rest) { 5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(rest); 5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new AbstractList<Object>() { 5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public int size() { 5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return rest.length + 2; 5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Object get(int index) { 5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert switch (index) { 5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case 0: 5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return first; 5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case 1: 5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return second; 5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert default: 5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return rest[index - 2]; 5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 557