/*
 * StringConcatenator class.
 *
 * Copyright (C) 2007 SATOH Takayuki All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package ts.util.text;

import java.text.Format;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Arrays;

/**
 * 文字列を連結するクラス。
 * <br>
 * 複数の文字列を、区切り文字を使って連結したり、同じ文字列を指定回数分繰り返し
 * て連結するなど、様々な方法で文字列を連結するためのメソッドを用意する。
 *
 * @author  佐藤隆之. 
 * @version $Revision: 1.1.1.1 $, $Date: 2010-10-16 00:03:52 $
 */
public class StringConcatenator
{
  /**
   * デフォルトコンストラクタ。
   */
  protected StringConcatenator()
  {}

  /**
   * 指定された文字列の配列を、区切り文字列を使って連結する。
   * <br>
   * 配列の要素にヌルが含まれていた場合は、その要素は<tt>"null"</tt>として
   * 連結する。
   *
   * @param  strings 文字列の配列。
   * @param  delimiter 区切り文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(String[] strings, String delimiter)
  {
    assert (strings != null) : "@param:strings is null.";
    assert (delimiter != null) : "@param:delimiter is null.";

    StringBuilder buf = new StringBuilder();
    if (strings.length > 0) {
      buf.append(strings[0]);
      for (int i=1; i<strings.length; i++) {
        buf.append(delimiter).append(strings[i]);
      }
    }
    return buf.toString();
  }

  /**
   * 指定された列挙オブジェクトに含まれる文字列を、区切り文字列を使って連結
   * する。
   * <br>
   * 列挙オブジェクトの要素にヌルが含まれていた場合は、その要素は
   * <tt>"null"</tt>として連結する。
   *
   * @param  enm 連結対象の文字列を含む列挙オブジェクト。
   * @param  delimiter 区切り文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(Enumeration<String> enm, String delimiter)
  {
    assert (enm != null) : "@param:enm is null.";
    assert (delimiter != null) : "@param:delimiter is null.";

    StringBuilder buf = new StringBuilder();
    if (enm.hasMoreElements()) {
      buf.append(enm.nextElement());
      while (enm.hasMoreElements()) {
        buf.append(delimiter).append(enm.nextElement());
      }
    }
    return buf.toString();
  }

  /**
   * 指定されたコレクションオブジェクトに含まれる文字列を、区切り文字列を使って
   * 連結する。
   * <br>
   * コレクションオブジェクトの要素のヌルが含まれていた場合は、その要素を
   * <tt>"null"</tt>として連結する。
   *
   * @param  coll 連結対処の文字列を含むコレクションオブジェクト。
   * @param  delimiter 区切り文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(Collection<String> coll, String delimiter)
  {
    assert (coll != null) : "@param:coll is null.";
    assert (delimiter != null) : "@param;delimiter is null.";

    StringBuilder buf = new StringBuilder();
    Iterator<String> it = coll.iterator();
    if (it.hasNext()) {
      buf.append(it.next());
      while (it.hasNext()) {
        buf.append(delimiter).append(it.next());
      }
    }
    return buf.toString();
  }

  /**
   * 指定された文字を、指定回数分繰り返し連結する。
   * <br>
   * 配列の要素にヌルが含まれていた場合は、その要素は<tt>"null"</tt>として
   * 連結する。
   *
   * @param  repeated 繰り返しの対象文字。
   * @param  count 繰り返し回数。
   * @return 連結後の文字列。
   * @throws AssertionError 繰り返し回数が負の場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #repeat(String,int)}を使用して下さい。
   */
  @Deprecated
  public static String repeat(char repeated, int count)
  {
     assert (count >= 0) : "@param:count is negative.";

     StringBuilder buf = new StringBuilder();
     for (int i=0; i<count; i++) {
       buf.append(repeated);
     }
     return buf.toString();
  }

  /**
   * 指定された文字列を、指定回数分繰り返し連結する。
   * <br>
   * 配列の要素にヌルが含まれていた場合は、その要素は<tt>"null"</tt>として
   * 連結する。
   *
   * @param  repeated 繰り返しの対象文字列。
   * @param  count 繰り返し回数。
   * @return 連結後の文字列。
   * @throws AssertionError 対象文字列がヌルの場合、又は繰り返し回数が負の場合
   *          （デバッグモードのみ）。
   */
  public static String repeat(String repeated, int count)
  {
     assert (repeated != null) : "@param:repeated is null.";
     assert (count >= 0) : "@param:count is negative.";

     StringBuilder buf = new StringBuilder();
     for (int i=0; i<count; i++) {
       buf.append(repeated);
     }
     return buf.toString();
  }

  /**
   * 指定された文字列を、区切り文字列を付加して、指定回数分繰り返し連結する。
   *
   * @param  repeated 繰り返しの対象文字列。
   * @param  count 繰り返し回数。
   * @param  delimiter 区切り文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合、又は繰り返し回数が負の場合
   *           （デバッグモードのみ）。
   */
  public static String repeat(String repeated, int count, String delimiter)
  {
    assert (repeated != null) : "@param:repeated is null.";
    assert (delimiter != null) : "@param:delimiter is null.";
    assert (count >= 0) : "@param:count is negative.";

    StringBuilder buf = new StringBuilder();
    if (count > 0) {
      buf.append(repeated);
      for (int i=1; i<count; i++) {
        buf.append(delimiter).append(repeated);
      }
    }
    return buf.toString();
  }

  /**
   * 指定された配列内のオブジェクトを、書式オブジェクトを使って文字列に変換し、
   * 区切り文字列を付加して連結する。
   *
   * @param  objs  オブジェクトの配列。
   * @param  fmt   書式オブジェクト。
   * @param  delim 区切り文字列。
   * @return 連結後の文字列。
   * @throws IllegalArgumentException 書式オブジェクトによる文字列への変換に
   *           失敗した場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(Object[] objs, Format fmt, String delim)
    throws IllegalArgumentException
  {
    assert (objs != null) : "@param:objs is null.";
    assert (fmt != null) : "@param:fmt is null.";
    assert (delim != null) : "@param:delim is null.";

    if (fmt instanceof MessageFormat) {
      MessageFormat mf = (MessageFormat) fmt;
      Object[] args = new Object[1];
      StringBuilder sb = new StringBuilder();
      if (objs.length > 0) {
        args[0] = objs[0];
        sb.append(MessageFormat.format(mf.toPattern(), args));
        for (int i=1; i<objs.length; i++) {
          args[0] = objs[i];
          sb.append(delim).append(MessageFormat.format(mf.toPattern(), args));
        }
      }
      return sb.toString();
    }
    else {
      StringBuilder sb = new StringBuilder();
      if (objs.length > 0) {
        sb.append(fmt.format(objs[0]));
        for (int i=1; i<objs.length; i++) {
          sb.append(delim).append(fmt.format(objs[i]));
        }
      }
      return sb.toString();
    }
  }

  /**
   * 指定された列挙オブジェクト内の要素オブジェクトを、書式オブジェクトを使って
   * 文字列に変換し、区切り文字列を付加して連結する。
   *
   * @param  enm 列挙オブジェクト。
   * @param  fmt 書式オブジェクト。
   * @param  delim 区切り文字列。
   * @return 連結後の文字列。
   * @throws IllegalArgumentException 書式オブジェクトによる文字列への変換に
   *           失敗した場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(Enumeration<Object> enm, Format fmt,
    String delim) throws IllegalArgumentException
  {
    assert (enm != null) : "@param:enm is null.";
    assert (fmt != null) : "@param:fmt is null.";
    assert (delim != null) : "@param:delim is null.";

    if (fmt instanceof MessageFormat) {
      MessageFormat mf = (MessageFormat) fmt;
      Object[] args = new Object[1];
      StringBuilder sb = new StringBuilder();
      if (enm.hasMoreElements()) {
        args[0] = enm.nextElement();
        sb.append(MessageFormat.format(mf.toPattern(), args));
        while (enm.hasMoreElements()) {
          args[0] = enm.nextElement();
          sb.append(delim).append(MessageFormat.format(mf.toPattern(), args));
        }
      }
      return sb.toString();
    }
    else {
      StringBuilder sb = new StringBuilder();
      if (enm.hasMoreElements()) {
        sb.append(fmt.format(enm.nextElement()));
        while (enm.hasMoreElements()) {
          sb.append(delim).append(fmt.format(enm.nextElement()));
        }
      }
      return sb.toString();
    }
  }

  /**
   * 指定されたコレクションオブジェクト内の要素オブジェクトを、書式オブジェクト
   * を使って文字列に変換し、区切り文字を付加して連結する。
   *
   * @param  coll コレクションオブジェクト。
   * @param  fmt 書式オブジェクト。
   * @param  delim 区切り文字列。
   * @return 連結後の文字列。
   * @throws IllegalArgumentException 書式オブジェクトによる文字列への変換に
   *           失敗した場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。 
   */
  public static String concatenate(Collection coll, Format fmt,
    String delim) throws IllegalArgumentException
  {
    assert (coll != null) : "@param:coll is null.";
    assert (fmt != null) : "@param:fmt is null.";
    assert (delim != null) : "@param:delim is null.";

    if (fmt instanceof MessageFormat) {
      MessageFormat mf = (MessageFormat) fmt;
      Object[] args = new Object[1];
      StringBuilder sb = new StringBuilder();
      Iterator it = coll.iterator();
      if (it.hasNext()) {
        args[0] = it.next();
        sb.append(MessageFormat.format(mf.toPattern(), args));
        while (it.hasNext()) {
          args[0] = it.next();
          sb.append(delim).append(MessageFormat.format(mf.toPattern(), args));
        }
      }
      return sb.toString();
    }
    else {
      StringBuilder sb = new StringBuilder();
      Iterator it = coll.iterator();
      if (it.hasNext()) {
        sb.append(fmt.format(it.next()));
        while (it.hasNext()) {
          sb.append(delim).append(fmt.format(it.next()));
        }
      }
      return sb.toString();
    }
  }

  /**
   * 指定された文字列の配列を、区切り文字列を使って連結する。
   * <br>
   * 区切り文字列が文字列中に現れる場合は、引数のエスケープ文字列をその直前に
   * 挿入する。
   * <br>
   * 配列の要素にヌルが含まれていた場合は、その要素は<tt>"null"</tt>として
   * 連結する。
   *
   * @param  strs 文字列の配列。
   * @param  delim 区切り文字列。
   * @param  escape エスケープ文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(String[] strs, String delim, String escape)
  {
    assert (strs != null) : "@param:strs is null.";
    assert (delim != null) : "@param:delim is null.";
    assert (escape != null) : "@param:escape is null.";

    Collection<String> spL = Arrays.asList(delim);

    StringBuilder buf = new StringBuilder();
    if (strs.length > 0) {
      buf.append(StringConverter.toWriteString(strs[0], escape, spL));
      for (int i=1; i<strs.length; i++) {
        buf.append(delim);
        buf.append(StringConverter.toWriteString(strs[i], escape, spL));
      }
    }
    return buf.toString();
  }

  /**
   * 指定された文字列の配列を、区切り文字を使って連結する。
   * <br>
   * 区切り文字が文字列中に現れる場合は、引数のエスケープ文字をその直前に挿入
   * する。
   * <br>
   * 配列の要素にヌルが含まれていた場合は、その要素は<tt>"null"</tt>として
   * 連結する。
   *
   * @param  strs 文字列の配列。
   * @param  delim 区切り文字。
   * @param  escape エスケープ文字。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #concatenate(String[],String,String)}を使用して下さい。
   */
  @Deprecated
  public static String concatenate(String[] strs, char delim, char escape)
  {
    assert (strs != null) : "@param:strs is null.";

    StringBuilder specChars = new StringBuilder();
    specChars.append(delim);

    StringBuilder buf = new StringBuilder();
    if (strs.length > 0) {
      buf.append(StringConverter.toWriteString(strs[0], escape, specChars));
      for (int i=1; i<strs.length; i++) {
        buf.append(delim);
        buf.append(StringConverter.toWriteString(strs[i], escape, specChars));
      }
    }
    return buf.toString();
  }

  /**
   * 指定された列挙オブジェクト内の要素文字列を、区切り文字を使って連結する。
   * <br>
   * 区切り文字が文字列中に現れる場合は、引数のエスケープ文字をその直前に挿入
   * する。
   *
   * @param  enm 列挙オブジェクト。
   * @param  delim 区切り文字。
   * @param  esc エスケープ文字。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #concatenate(java.util.Enumeration,String,String)}を使用して下さい。
   */
  @Deprecated
  public static String concatenate(
    Enumeration<String> enm, char delim, char esc)
  {
    assert (enm != null) : "@param:enm is null.";

    StringBuilder spe = new StringBuilder();
    spe.append(delim);
    
    StringBuilder buf = new StringBuilder();
    if (enm.hasMoreElements()) {
      buf.append(StringConverter.toWriteString(enm.nextElement(), esc, spe));
      while (enm.hasMoreElements()) {
        buf.append(delim);
        buf.append(StringConverter.toWriteString(enm.nextElement(), esc, spe));
      }
    }
    return buf.toString();
  }

  /**
   * 指定された列挙オブジェクト内の要素文字列を、区切り文字列を使って連結する。
   * <br>
   * 区切り文字列が文字列中に現れる場合は、引数のエスケープ文字列をその直前に
   * 挿入する。
   *
   * @param  enm 列挙オブジェクト。
   * @param  delim 区切り文字列。
   * @param  esc エスケープ文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(
    Enumeration<String> enm, String delim, String esc)
  {
    assert (enm != null) : "@param:enm is null.";
    assert (delim != null) : "@param:delim is null.";
    assert (esc != null) : "@param:esc is null.";

    Collection<String> spL = Arrays.asList(delim);
    
    StringBuilder buf = new StringBuilder();
    if (enm.hasMoreElements()) {
      buf.append(StringConverter.toWriteString(enm.nextElement(), esc, spL));
      while (enm.hasMoreElements()) {
        buf.append(delim);
        buf.append(StringConverter.toWriteString(enm.nextElement(), esc, spL));
      }
    }
    return buf.toString();
  }

  /**
   * 指定されたコレクションオブジェクト内の要素文字列を、区切り文字を使って
   * 連結する。
   * <br>
   * 区切り文字が文字列中に現れる場合は、引数のエスケープ文字をその直前に挿入
   * する。
   *
   * @param  coll コレクションオブジェクト。
   * @param  delim 区切り文字。
   * @param  esc エスケープ文字。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #concatenate(java.util.Collection,String,String)}を使用して下さい。
   */
  @Deprecated
  public static String concatenate(
    Collection<String> coll, char delim, char esc)
  {
    assert (coll != null) : "@param:coll is null.";

    StringBuilder spe = new StringBuilder();
    spe.append(delim);

    StringBuilder buf = new StringBuilder();
    Iterator<String> it = coll.iterator();
    if (it.hasNext()) {
      buf.append(StringConverter.toWriteString(it.next(), esc, spe));
      while (it.hasNext()) {
        buf.append(delim);
        buf.append(StringConverter.toWriteString(it.next(), esc, spe));
      }
    }
    return buf.toString();
  }

  /**
   * 指定されたコレクションオブジェクト内の要素文字列を、区切り文字列を使って
   * 連結する。
   * <br>
   * 区切り文字列が文字列中に現れる場合は、引数のエスケープ文字列をその直前に
   * 挿入する。
   *
   * @param  coll コレクションオブジェクト。
   * @param  delim 区切り文字列。
   * @param  esc エスケープ文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(
    Collection<String> coll, String delim, String esc)
  {
    assert (coll != null) : "@param:coll is null.";
    assert (delim != null) : "@param:delim is null.";
    assert (esc != null) : "@param:esc is null.";

    Collection<String> spL = Arrays.asList(delim);

    StringBuilder buf = new StringBuilder();
    Iterator<String> it = coll.iterator();
    if (it.hasNext()) {
      buf.append(StringConverter.toWriteString(it.next(), esc, spL));
      while (it.hasNext()) {
        buf.append(delim);
        buf.append(StringConverter.toWriteString(it.next(), esc, spL));
      }
    }
    return buf.toString();
  }

  /**
   * 指定された文字列の配列を、括弧で囲み、区切り文字を使って連結する。
   * <br>
   * 区切り文字や括弧が文字列中に現れる場合は、引数のエスケープ文字をその直前
   * に挿入する。
   *
   * @param  strs 文字列の配列。
   * @param  delim 区切り文字。
   * @param  openPar 開き括弧。
   * @param  closePar 閉じ括弧。
   * @param  escape エスケープ文字。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #concatenate(String[],String,String,String,String)}を使用して下さい。
   */
  @Deprecated
  public static String concatenate(String[] strs, char delim,
    char openPar, char closePar, char escape)
  {
    assert (strs != null) : "@param:strs is null.";

    StringBuilder specChars = new StringBuilder();
    specChars.append(delim);
    specChars.append(openPar);
    specChars.append(closePar);

    StringBuilder buf = new StringBuilder();
    if (strs.length > 0) {
      buf.append(openPar);
      buf.append(StringConverter.toWriteString(strs[0], escape, specChars));
      buf.append(closePar);
      for (int i=1; i<strs.length; i++) {
        buf.append(delim);
        buf.append(openPar);
        buf.append(StringConverter.toWriteString(strs[i], escape, specChars));
        buf.append(closePar);
      }
    }
    return buf.toString();
  }

  /**
   * 指定された文字列の配列を、括弧で囲み、区切り文字列を使って連結する。
   * <br>
   * 区切り文字列や括弧が文字列中に現れる場合は、引数のエスケープ文字列をその
   * 直前に挿入する。
   *
   * @param  strs 文字列の配列。
   * @param  delim 区切り文字。
   * @param  openPar 開き括弧。
   * @param  closePar 閉じ括弧。
   * @param  escape エスケープ文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(String[] strs, String delim,
    String openPar, String closePar, String escape)
  {
    assert (strs != null) : "@param:strs is null.";
    assert (delim != null) : "@param:delim is null.";
    assert (openPar != null) : "@param:openPar is null.";
    assert (closePar != null) : "@param:closePar is null.";
    assert (escape != null) : "@param:escape is null.";

    Collection<String> spL = Arrays.asList(delim, openPar, closePar);

    StringBuilder buf = new StringBuilder();
    if (strs.length > 0) {
      buf.append(openPar);
      buf.append(StringConverter.toWriteString(strs[0], escape, spL));
      buf.append(closePar);
      for (int i=1; i<strs.length; i++) {
        buf.append(delim);
        buf.append(openPar);
        buf.append(StringConverter.toWriteString(strs[i], escape, spL));
        buf.append(closePar);
      }
    }
    return buf.toString();
  }

  /**
   * 指定された列挙オブジェクト内の要素文字列を、括弧で囲み、区切り文字を
   * 使って連結する。
   * <br>
   * 区切り文字や括弧が文字列中に現れる場合は、引数のエスケープ文字をその直前
   * に挿入する。
   *
   * @param  enm 列挙オブジェクト。
   * @param  delim 区切り文字。
   * @param  openPar 開き括弧。
   * @param  closePar 閉じ括弧。
   * @param  escape エスケープ文字。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #concatenate(java.util.Enumeration,String,String,String,String)}
   *   を使用して下さい。
   */
  @Deprecated
  public static String concatenate(Enumeration<String> enm, char delim,
    char openPar, char closePar, char escape)
  {
    assert (enm != null) : "@param:enm is null.";

    StringBuilder specChars = new StringBuilder();
    specChars.append(delim);
    specChars.append(openPar);
    specChars.append(closePar);

    StringBuilder buf = new StringBuilder();
    if (enm.hasMoreElements()) {
      buf.append(openPar);
      buf.append(StringConverter.toWriteString(
        enm.nextElement(), escape, specChars));
      buf.append(closePar);
      while (enm.hasMoreElements()) {
        buf.append(delim);
        buf.append(openPar);
        buf.append(StringConverter.toWriteString(
          enm.nextElement(), escape, specChars));
        buf.append(closePar);
      }
    }
    return buf.toString();
  }

  /**
   * 指定された列挙オブジェクト内の要素文字列を、括弧で囲み、区切り文字列を
   * 使って連結する。
   * <br>
   * 区切り文字列や括弧が文字列中に現れる場合は、引数のエスケープ文字列をその
   * 直前に挿入する。
   *
   * @param  enm 列挙オブジェクト。
   * @param  delim 区切り文字列。
   * @param  openPar 開き括弧。
   * @param  closePar 閉じ括弧。
   * @param  escape エスケープ文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(Enumeration<String> enm, String delim,
    String openPar, String closePar, String escape)
  {
    assert (enm != null) : "@param:enm is null.";
    assert (delim != null) : "@param:delim is null.";
    assert (openPar != null) : "@param:openPar is null.";
    assert (closePar != null) : "@param:closePar is null.";
    assert (escape != null) : "@param:escape is null.";

    Collection<String> spL = Arrays.asList(delim, openPar, closePar);

    StringBuilder buf = new StringBuilder();
    if (enm.hasMoreElements()) {
      buf.append(openPar);
      buf.append(StringConverter.toWriteString(enm.nextElement(), escape, spL));
      buf.append(closePar);
      while (enm.hasMoreElements()) {
        buf.append(delim);
        buf.append(openPar);
        buf.append(StringConverter.toWriteString(enm.nextElement(),escape,spL));
        buf.append(closePar);
      }
    }
    return buf.toString();
  }

  /**
   * 指定されたコレクションオブジェクト内の要素文字列を、括弧で囲み、区切り文字
   * を使って連結する。
   * <br>
   * 区切り文字や括弧が文字列中に現れる場合は、引数のエスケープ文字をその直前に
   * 挿入する。
   *
   * @param  coll コレクションオブジェクト。
   * @param  delim 区切り文字。
   * @param  openPar 開き括弧。
   * @param  closePar 閉じ括弧。
   * @param  escape エスケープ文字。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   * @deprecated <code>char</code>変数の使用を避けるため廃止。代わりに{@link
   *   #concatenate(java.util.Collection,String,String,String,String)}を使用
   *   して下さい。
   */
  @Deprecated
  public static String concatenate(Collection<String> coll, char delim,
    char openPar, char closePar, char escape)
  {
    assert (coll != null) : "@param:coll is null.";

    StringBuilder specChars = new StringBuilder();
    specChars.append(delim);
    specChars.append(openPar);
    specChars.append(closePar);

    StringBuilder buf = new StringBuilder();
    Iterator<String> it = coll.iterator();
    if (it.hasNext()) {
      buf.append(openPar);
      buf.append(StringConverter.toWriteString(it.next(), escape, specChars));
      buf.append(closePar);
      while (it.hasNext()) {
        buf.append(delim);
        buf.append(openPar);
        buf.append(StringConverter.toWriteString(it.next(), escape, specChars));
        buf.append(closePar);
      }
    }
    return buf.toString();
  }

  /**
   * 指定されたコレクションオブジェクト内の要素文字列を、括弧で囲み、
   * 区切り文字列を使って連結する。
   * <br>
   * 区切り文字列や括弧が文字列中に現れる場合は、引数のエスケープ文字列をその
   * 直前に挿入する。
   *
   * @param  coll コレクションオブジェクト。
   * @param  delim 区切り文字列。
   * @param  openPar 開き括弧。
   * @param  closePar 閉じ括弧。
   * @param  escape エスケープ文字列。
   * @return 連結後の文字列。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  public static String concatenate(Collection<String> coll, String delim,
    String openPar, String closePar, String escape)
  {
    assert (coll != null) : "@param:coll is null.";
    assert (delim != null) : "@param:delim is null.";
    assert (openPar != null) : "@param:openPar is null.";
    assert (closePar != null) : "@param:closePar is null.";
    assert (escape != null) : "@param:escape is null.";

    Collection<String> spL = Arrays.asList(delim, openPar, closePar);

    StringBuilder buf = new StringBuilder();
    Iterator<String> it = coll.iterator();
    if (it.hasNext()) {
      buf.append(openPar);
      buf.append(StringConverter.toWriteString(it.next(), escape, spL));
      buf.append(closePar);
      while (it.hasNext()) {
        buf.append(delim);
        buf.append(openPar);
        buf.append(StringConverter.toWriteString(it.next(), escape, spL));
        buf.append(closePar);
      }
    }
    return buf.toString();
  }
}
