com.google.common.base.Join.java Source code

Java tutorial

Introduction

Here is the source code for com.google.common.base.Join.java

Source

/*
 * Copyright (C) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.base;

import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * Join is the only utility for joining pieces of text separated by a
 * delimiter that you will ever need. It can handle Iterators, Collections,
 * arrays, and varargs, and can append to any Appendable or just return a
 * String.
 * <p>
 * A trivial example: {@code join(":", "a", "b", "c")}
 * gives {@code "a:b:c"}.  See JoinTest for more examples.
 * <p>
 * All the methods of this class throw {@link NullPointerException} when a
 * value of {@code null} is supplied for any parameter. The elements within
 * the collection, iterator, array, or varargs parameter list <i>may</i> be
 * null -- these will be represented in the output with the string
 * {@code "null"}.
 *
 * @author Kevin Bourrillion
 */
public final class Join {
    private Join() {
    }

    /**
     * Appends each of the {@code tokens} to {@code appendable}, separated by
     * {@code delimiter}.
     *
     * @param appendable the non-null object to append the results to
     * @param delimiter a non-null String to append between every element, but not
     *          at the beginning or end
     * @param tokens Objects of any type. For each element, if it is an instance
     *          of {@link CharSequence} it will be appended as-is, otherwise it
     *          will be converted to a {@code CharSequence} using
     *          {@link String#valueOf(Object)}. Note that this implies that null
     *          tokens will be appended as the four-character string
     *          {@code "null"}.
     * @return The same appendable instance that was passed in
     * @throws JoinException if an IOException occurs
     */
    public static <T extends Appendable> T join(T appendable, String delimiter, Iterator<?> tokens) {

        /* This method is the workhorse of the class */

        checkNotNull(appendable);
        checkNotNull(delimiter);
        checkNotNull(tokens);
        if (tokens.hasNext()) {
            try {
                appendOneToken(appendable, tokens.next());
                while (tokens.hasNext()) {
                    appendable.append(delimiter);
                    appendOneToken(appendable, tokens.next());
                }
            } catch (IOException e) {
                throw new JoinException(e);
            }
        }
        return appendable;
    }

    /**
     * Returns a String containing the {@code tokens}, converted to Strings if
     * necessary, separated by {@code delimiter}.  If {@code tokens} is empty,
     * returns the empty string.
     */
    public static String join(String delimiter, Iterable<?> tokens) {
        checkNotNull(tokens);
        return join(delimiter, tokens.iterator());
    }

    /**
     * Variant of {@link #join(Appendable,String,Iterator)} where {@code tokens}
     * is an {@code Iterable}.
     */
    public static <T extends Appendable> T join(T appendable, String delimiter, Iterable<?> tokens) {
        checkNotNull(tokens);
        return join(appendable, delimiter, tokens.iterator());
    }

    /**
     * Variant of {@link #join(Appendable,String,Iterator)} where {@code tokens}
     * is an array.
     */
    public static <T extends Appendable> T join(T appendable, String delimiter, Object[] tokens) {
        checkNotNull(tokens);
        return join(appendable, delimiter, Arrays.asList(tokens));
    }

    /**
     * Variant of {@link #join(Appendable,String,Iterator)} for tokens given using
     * varargs.
     */
    public static <T extends Appendable> T join(T appendable, String delimiter, @Nullable Object firstToken,
            Object... otherTokens) {
        checkNotNull(otherTokens);
        return join(appendable, delimiter, asList(firstToken, otherTokens));
    }

    /**
     * Variant of {@link #join(String,Iterable)} where {@code tokens} is an
     * {@code Iterator}.
     */
    public static String join(String delimiter, Iterator<?> tokens) {
        StringBuilder sb = new StringBuilder();
        join(sb, delimiter, tokens);
        return sb.toString();
    }

    /**
     * Variant of {@link #join(String,Iterable)} where {@code tokens} is an
     * array.
     */
    public static String join(String delimiter, Object[] tokens) {
        checkNotNull(tokens);
        return join(delimiter, Arrays.asList(tokens));
    }

    /**
     * Variant of {@link #join(String,Iterable)} for tokens given using varargs.
     */
    public static String join(String delimiter, @Nullable Object firstToken, Object... otherTokens) {
        checkNotNull(otherTokens);
        return join(delimiter, asList(firstToken, otherTokens));
    }

    private static void appendOneToken(Appendable appendable, Object token) throws IOException {
        appendable.append(toCharSequence(token));
    }

    private static CharSequence toCharSequence(Object token) {
        return (token instanceof CharSequence) ? (CharSequence) token : String.valueOf(token);
    }

    /**
     * Thrown in response to an {@link IOException} from the supplied
     * {@link Appendable}.  This is used because most callers won't want to
     * worry about catching an IOException.
     */
    public static class JoinException extends RuntimeException {
        private JoinException(IOException cause) {
            super(cause);
        }

        private static final long serialVersionUID = 1L;
    }

    /**
     * Duplicate of
     * {@link com.google.common.collect.Lists#asList(Object, Object[])}.
     * copied here to remove dependencies.
     */
    private static List<Object> asList(final Object first, final Object[] rest) {
        return new AbstractList<Object>() {
            @Override
            public int size() {
                return rest.length + 1;
            }

            @Override
            public Object get(int index) {
                return (index == 0) ? first : rest[index - 1];
            }
        };
    }
}