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