/*
 * Copyright (C) 2007 The Guava Authors
 *
 * 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.collect;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkRemove;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * An assortment of mainly legacy static utility methods that operate on or return objects of type
 * {@code Iterable}. Except as noted, each method has a corresponding {@link Iterator}-based method
 * in the {@link Iterators} class.
 *
 *
Java 8 users: several common uses for this class are now more comprehensively addressed
 * by the new {@link java.util.stream.Stream} library. Read the method documentation below for
 * comparisons. This class is not being deprecated, but we gently encourage you to migrate to
 * streams.
 *
 *
Performance notes: Unless otherwise noted, all of the iterables produced in this class
 * are lazy, which means that their iterators only advance the backing iteration when
 * absolutely necessary.
 *
 *
See the Guava User Guide article on  {@code
 * Iterables}.
 *
 * @author Kevin Bourrillion
 * @author Jared Levy
 * @since 2.0
 */
@GwtCompatible(emulated = true)
public final class Iterables {
  private Iterables() {}

  /** Returns an unmodifiable view of {@code iterable}. */
  public static <T> Iterable<T> unmodifiableIterable(final Iterable<? extends T> iterable) {
    checkNotNull(iterable);
    if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) {
      @SuppressWarnings("unchecked") // Since it's unmodifiable, the covariant cast is safe
      Iterable<T> result = (Iterable<T>) iterable;
      return result;
    }
    return new UnmodifiableIterable<>(iterable);
  }

  /**
   * Simply returns its argument.
   *
   * @deprecated no need to use this
   * @since 10.0
   */
  @Deprecated
  public static <E> Iterable<E> unmodifiableIterable(ImmutableCollection<E> iterable) {
    return checkNotNull(iterable);
  }

  private static final class UnmodifiableIterable<T> extends FluentIterable<T> {
    private final Iterable<? extends T> iterable;

    private UnmodifiableIterable(Iterable<? extends T> iterable) {
      this.iterable = iterable;
    }

    @Override
    public Iterator<T> iterator() {
      return Iterators.unmodifiableIterator(iterable.iterator());
    }

    @Override
    public void forEach(Consumer<? super T> action) {
      iterable.forEach(action);
    }

    @SuppressWarnings("unchecked") // safe upcast, assuming no one has a crazy Spliterator subclass
    @Override
    public Spliterator<T> spliterator() {
      return (Spliterator<T>) iterable.spliterator();
    }

    @Override
    public String toString() {
      return iterable.toString();
    }
    // no equals and hashCode; it would break the contract!
  }

  /** Returns the number of elements in {@code iterable}. */
  public static int size(Iterable<?> iterable) {
    return (iterable instanceof Collection)
        ? ((Collection<?>) iterable).size()
        : Iterators.size(iterable.iterator());
  }

  /**
   * Returns {@code true} if {@code iterable} contains any element {@code o} for which {@code
   * Objects.equals(o, element)} would return {@code true}. Otherwise returns {@code false}, even in
   * cases where {@link Collection#contains} might throw {@link NullPointerException} or {@link
   * ClassCastException}.
   */
  public static boolean contains(Iterable<?> iterable, @Nullable Object element) {
    if (iterable instanceof Collection) {
      Collection<?> collection = (Collection<?>) iterable;
      return Collections2.safeContains(collection, element);
    }
    return Iterators.contains(iterable.iterator(), element);
  }

  /**
   * Removes, from an iterable, every element that belongs to the provided collection.
   *
   *
This method calls {@link Collection#removeAll} if {@code iterable} is a collection, and
   * {@link Iterators#removeAll} otherwise.
   *
   * @param removeFrom the iterable to (potentially) remove elements from
   * @param elementsToRemove the elements to remove
   * @return {@code true} if any element was removed from {@code iterable}
   */
  @CanIgnoreReturnValue
  public static boolean removeAll(Iterable<?> removeFrom, Collection<?> elementsToRemove) {
    return (removeFrom instanceof Collection)
        ? ((Collection<?>) removeFrom).removeAll(checkNotNull(elementsToRemove))
        : Iterators.removeAll(removeFrom.iterator(), elementsToRemove);
  }

  /**
   * Removes, from an iterable, every element that does not belong to the provided collection.
   *
   *
This method calls {@link Collection#retainAll} if {@code iterable} is a collection, and
   * {@link Iterators#retainAll} otherwise.
   *
   * @param removeFrom the iterable to (potentially) remove elements from
   * @param elementsToRetain the elements to retain
   * @return {@code true} if any element was removed from {@code iterable}
   */
  @CanIgnoreReturnValue
  public static boolean retainAll(Iterable<?> removeFrom, Collection<?> elementsToRetain) {
    return (removeFrom instanceof Collection)
        ? ((Collection<?>) removeFrom).retainAll(checkNotNull(elementsToRetain))
        : Iterators.retainAll(removeFrom.iterator(), elementsToRetain);
  }

  /**
   * Removes, from an iterable, every element that satisfies the provided predicate.
   *
   *
Removals may or may not happen immediately as each element is tested against the predicate.
   * The behavior of this method is not specified if {@code predicate} is dependent on {@code
   * removeFrom}.
   *
   *
Java 8 users: if {@code removeFrom} is a {@link Collection}, use {@code
   * removeFrom.removeIf(predicate)} instead.
   *
   * @param removeFrom the iterable to (potentially) remove elements from
   * @param predicate a predicate that determines whether an element should be removed
   * @return {@code true} if any elements were removed from the iterable
   * @throws UnsupportedOperationException if the iterable does not support {@code remove()}.
   * @since 2.0
   */
  @CanIgnoreReturnValue
  public static <T> boolean removeIf(Iterable<T> removeFrom, Predicate<? super T> predicate) {
    if (removeFrom instanceof Collection) {
      return ((Collection<T>) removeFrom).removeIf(predicate);
    }
    return Iterators.removeIf(removeFrom.iterator(), predicate);
  }

  /** Removes and returns the first matching element, or returns {@code null} if there is none. */
  static <T> @Nullable T removeFirstMatching(
      Iterable<T> removeFrom, Predicate<? super T> predicate) {
    checkNotNull(predicate);
    Iterator<T> iterator = removeFrom.iterator();
    while (iterator.hasNext()) {
      T next = iterator.next();
      if (predicate.apply(next)) {
        iterator.remove();
        return next;
      }
    }
    return null;
  }

  /**
   * Determines whether two iterables contain equal elements in the same order. More specifically,
   * this method returns {@code true} if {@code iterable1} and {@code iterable2} contain the same
   * number of elements and every element of {@code iterable1} is equal to the corresponding element
   * of {@code iterable2}.
   */
  public static boolean elementsEqual(Iterable<?> iterable1, Iterable<?> iterable2) {
    if (iterable1 instanceof Collection && iterable2 instanceof Collection) {
      Collection<?> collection1 = (Collection<?>) iterable1;
      Collection<?> collection2 = (Collection<?>) iterable2;
      if (collection1.size() != collection2.size()) {
        return false;
      }
    }
    return Iterators.elementsEqual(iterable1.iterator(), iterable2.iterator());
  }

  /**
   * Returns a string representation of {@code iterable}, with the format {@code [e1, e2, ..., en]}
   * (that is, identical to {@link java.util.Arrays Arrays}{@code
   * .toString(Iterables.toArray(iterable))}). Note that for most implementations of {@link
   * Collection}, {@code collection.toString()} also gives the same result, but that behavior is not
   * generally guaranteed.
   */
  public static String toString(Iterable<?> iterable) {
    return Iterators.toString(iterable.iterator());
  }

  /**
   * Returns the single element contained in {@code iterable}.
   *
   *
Java 8 users: the {@code Stream} equivalent to this method is {@code
   * stream.collect(MoreCollectors.onlyElement())}.
   *
   * @throws NoSuchElementException if the iterable is empty
   * @throws IllegalArgumentException if the iterable contains multiple elements
   */
  public static <T> T getOnlyElement(Iterable<T> iterable) {
    return Iterators.getOnlyElement(iterable.iterator());
  }

  /**
   * Returns the single element contained in {@code iterable}, or {@code defaultValue} if the
   * iterable is empty.
   *
   *
Java 8 users: the {@code Stream} equivalent to this method is {@code
   * stream.collect(MoreCollectors.toOptional()).orElse(defaultValue)}.
   *
   * @throws IllegalArgumentException if the iterator contains multiple elements
   */
  public static <T> @Nullable T getOnlyElement(
      Iterable<? extends T> iterable, @Nullable T defaultValue) {
    return Iterators.getOnlyElement(iterable.iterator(), defaultValue);
  }

  /**
   * Copies an iterable's elements into an array.
   *
   * @param iterable the iterable to copy
   * @param type the type of the elements
   * @return a newly-allocated array into which all the elements of the iterable have been copied
   */
  @GwtIncompatible // Array.newInstance(Class, int)
  public static <T> T[] toArray(Iterable<? extends T> iterable, Class<T> type) {
    return toArray(iterable, ObjectArrays.newArray(type, 0));
  }

  static <T> T[] toArray(Iterable<? extends T> iterable, T[] array) {
    Collection<? extends T> collection = castOrCopyToCollection(iterable);
    return collection.toArray(array);
  }

  /**
   * Copies an iterable's elements into an array.
   *
   * @param iterable the iterable to copy
   * @return a newly-allocated array into which all the elements of the iterable have been copied
   */
  static Object[] toArray(Iterable<?> iterable) {
    return castOrCopyToCollection(iterable).toArray();
  }

  /**
   * Converts an iterable into a collection. If the iterable is already a collection, it is
   * returned. Otherwise, an {@link java.util.ArrayList} is created with the contents of the
   * iterable in the same iteration order.
   */
  private static <E> Collection<E> castOrCopyToCollection(Iterable<E> iterable) {
    return (iterable instanceof Collection)
        ? (Collection<E>) iterable
        : Lists.newArrayList(iterable.iterator());
  }

  /**
   * Adds all elements in {@code iterable} to {@code collection}.
   *
   * @return {@code true} if {@code collection} was modified as a result of this operation.
   */
  @CanIgnoreReturnValue
  public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
    if (elementsToAdd instanceof Collection) {
      Collection<? extends T> c = Collections2.cast(elementsToAdd);
      return addTo.addAll(c);
    }
    return Iterators.addAll(addTo, checkNotNull(elementsToAdd).iterator());
  }

  /**
   * Returns the number of elements in the specified iterable that equal the specified object. This
   * implementation avoids a full iteration when the iterable is a {@link Multiset} or {@link Set}.
   *
   *
Java 8 users: In most cases, the {@code Stream} equivalent of this method is {@code
   * stream.filter(element::equals).count()}. If {@code element} might be null, use {@code
   * stream.filter(Predicate.isEqual(element)).count()} instead.
   *
   * @see java.util.Collections#frequency(Collection, Object) Collections.frequency(Collection,
   *     Object)
   */
  public static int frequency(Iterable<?> iterable, @Nullable Object element) {
    if ((iterable instanceof Multiset)) {
      return ((Multiset<?>) iterable).count(element);
    } else if ((iterable instanceof Set)) {
      return ((Set<?>) iterable).contains(element) ? 1 : 0;
    }
    return Iterators.frequency(iterable.iterator(), element);
  }

  /**
   * Returns an iterable whose iterators cycle indefinitely over the elements of {@code iterable}.
   *
   *
That iterator supports {@code remove()} if {@code iterable.iterator()} does. After {@code
   * remove()} is called, subsequent cycles omit the removed element, which is no longer in {@code
   * iterable}. The iterator's {@code hasNext()} method returns {@code true} until {@code iterable}
   * is empty.
   *
   *
Warning: Typical uses of the resulting iterator may produce an infinite loop. You
   * should use an explicit {@code break} or be certain that you will eventually remove all the
   * elements.
   *
   *
To cycle over the iterable {@code n} times, use the following: {@code
   * Iterables.concat(Collections.nCopies(n, iterable))}
   *
   *
Java 8 users: The {@code Stream} equivalent of this method is {@code
   * Stream.generate(() -> iterable).flatMap(Streams::stream)}.
   */
  public static <T> Iterable<T> cycle(final Iterable<T> iterable) {
    checkNotNull(iterable);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.cycle(iterable);
      }

      @Override
      public Spliterator<T> spliterator() {
        return Stream.generate(() -> iterable).flatMap(Streams::stream).spliterator();
      }

      @Override
      public String toString() {
        return iterable.toString() + " (cycled)";
      }
    };
  }

  /**
   * Returns an iterable whose iterators cycle indefinitely over the provided elements.
   *
   *
After {@code remove} is invoked on a generated iterator, the removed element will no longer
   * appear in either that iterator or any other iterator created from the same source iterable.
   * That is, this method behaves exactly as {@code Iterables.cycle(Lists.newArrayList(elements))}.
   * The iterator's {@code hasNext} method returns {@code true} until all of the original elements
   * have been removed.
   *
   *
Warning: Typical uses of the resulting iterator may produce an infinite loop. You
   * should use an explicit {@code break} or be certain that you will eventually remove all the
   * elements.
   *
   *
To cycle over the elements {@code n} times, use the following: {@code
   * Iterables.concat(Collections.nCopies(n, Arrays.asList(elements)))}
   *
   *
Java 8 users: If passing a single element {@code e}, the {@code Stream} equivalent of
   * this method is {@code Stream.generate(() -> e)}. Otherwise, put the elements in a collection
   * and use {@code Stream.generate(() -> collection).flatMap(Collection::stream)}.
   */
  @SafeVarargs
  public static <T> Iterable<T> cycle(T... elements) {
    return cycle(Lists.newArrayList(elements));
  }

  /**
   * Combines two iterables into a single iterable. The returned iterable has an iterator that
   * traverses the elements in {@code a}, followed by the elements in {@code b}. The source
   * iterators are not polled until necessary.
   *
   *
The returned iterable's iterator supports {@code remove()} when the corresponding input
   * iterator supports it.
   *
   *
Java 8 users: The {@code Stream} equivalent of this method is {@code Stream.concat(a,
   * b)}.
   */
  public static <T> Iterable<T> concat(Iterable<? extends T> a, Iterable<? extends T> b) {
    return FluentIterable.concat(a, b);
  }

  /**
   * Combines three iterables into a single iterable. The returned iterable has an iterator that
   * traverses the elements in {@code a}, followed by the elements in {@code b}, followed by the
   * elements in {@code c}. The source iterators are not polled until necessary.
   *
   *
The returned iterable's iterator supports {@code remove()} when the corresponding input
   * iterator supports it.
   *
   *
Java 8 users: The {@code Stream} equivalent of this method is {@code
   * Streams.concat(a, b, c)}.
   */
  public static <T> Iterable<T> concat(
      Iterable<? extends T> a, Iterable<? extends T> b, Iterable<? extends T> c) {
    return FluentIterable.concat(a, b, c);
  }

  /**
   * Combines four iterables into a single iterable. The returned iterable has an iterator that
   * traverses the elements in {@code a}, followed by the elements in {@code b}, followed by the
   * elements in {@code c}, followed by the elements in {@code d}. The source iterators are not
   * polled until necessary.
   *
   *
The returned iterable's iterator supports {@code remove()} when the corresponding input
   * iterator supports it.
   *
   *
Java 8 users: The {@code Stream} equivalent of this method is {@code
   * Streams.concat(a, b, c, d)}.
   */
  public static <T> Iterable<T> concat(
      Iterable<? extends T> a,
      Iterable<? extends T> b,
      Iterable<? extends T> c,
      Iterable<? extends T> d) {
    return FluentIterable.concat(a, b, c, d);
  }

  /**
   * Combines multiple iterables into a single iterable. The returned iterable has an iterator that
   * traverses the elements of each iterable in {@code inputs}. The input iterators are not polled
   * until necessary.
   *
   *
The returned iterable's iterator supports {@code remove()} when the corresponding input
   * iterator supports it.
   *
   *
Java 8 users: The {@code Stream} equivalent of this method is {@code
   * Streams.concat(...)}.
   *
   * @throws NullPointerException if any of the provided iterables is null
   */
  @SafeVarargs
  public static <T> Iterable<T> concat(Iterable<? extends T>... inputs) {
    return FluentIterable.concat(inputs);
  }

  /**
   * Combines multiple iterables into a single iterable. The returned iterable has an iterator that
   * traverses the elements of each iterable in {@code inputs}. The input iterators are not polled
   * until necessary.
   *
   *
The returned iterable's iterator supports {@code remove()} when the corresponding input
   * iterator supports it. The methods of the returned iterable may throw {@code
   * NullPointerException} if any of the input iterators is null.
   *
   *
Java 8 users: The {@code Stream} equivalent of this method is {@code
   * streamOfStreams.flatMap(s -> s)}.
   */
  public static <T> Iterable<T> concat(Iterable<? extends Iterable<? extends T>> inputs) {
    return FluentIterable.concat(inputs);
  }

  /**
   * Divides an iterable into unmodifiable sublists of the given size (the final iterable may be
   * smaller). For example, partitioning an iterable containing {@code [a, b, c, d, e]} with a
   * partition size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer iterable containing two
   * inner lists of three and two elements, all in the original order.
   *
   *
Iterators returned by the returned iterable do not support the {@link Iterator#remove()}
   * method. The returned lists implement {@link RandomAccess}, whether or not the input list does.
   *
   *
Note: if {@code iterable} is a {@link List}, use {@link Lists#partition(List, int)}
   * instead.
   *
   * @param iterable the iterable to return a partitioned view of
   * @param size the desired size of each partition (the last may be smaller)
   * @return an iterable of unmodifiable lists containing the elements of {@code iterable} divided
   *     into partitions
   * @throws IllegalArgumentException if {@code size} is nonpositive
   */
  public static <T> Iterable<List<T>> partition(final Iterable<T> iterable, final int size) {
    checkNotNull(iterable);
    checkArgument(size > 0);
    return new FluentIterable<List<T>>() {
      @Override
      public Iterator<List<T>> iterator() {
        return Iterators.partition(iterable.iterator(), size);
      }
    };
  }

  /**
   * Divides an iterable into unmodifiable sublists of the given size, padding the final iterable
   * with null values if necessary. For example, partitioning an iterable containing {@code [a, b,
   * c, d, e]} with a partition size of 3 yields {@code [[a, b, c], [d, e, null]]} -- an outer
   * iterable containing two inner lists of three elements each, all in the original order.
   *
   *
Iterators returned by the returned iterable do not support the {@link Iterator#remove()}
   * method.
   *
   * @param iterable the iterable to return a partitioned view of
   * @param size the desired size of each partition
   * @return an iterable of unmodifiable lists containing the elements of {@code iterable} divided
   *     into partitions (the final iterable may have trailing null elements)
   * @throws IllegalArgumentException if {@code size} is nonpositive
   */
  public static <T> Iterable<List<T>> paddedPartition(final Iterable<T> iterable, final int size) {
    checkNotNull(iterable);
    checkArgument(size > 0);
    return new FluentIterable<List<T>>() {
      @Override
      public Iterator<List<T>> iterator() {
        return Iterators.paddedPartition(iterable.iterator(), size);
      }
    };
  }

  /**
   * Returns a view of {@code unfiltered} containing all elements that satisfy the input predicate
   * {@code retainIfTrue}. The returned iterable's iterator does not support {@code remove()}.
   *
   *
{@code Stream} equivalent: {@link Stream#filter}.
   */
  public static <T> Iterable<T> filter(
      final Iterable<T> unfiltered, final Predicate<? super T> retainIfTrue) {
    checkNotNull(unfiltered);
    checkNotNull(retainIfTrue);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.filter(unfiltered.iterator(), retainIfTrue);
      }

      @Override
      public void forEach(Consumer<? super T> action) {
        checkNotNull(action);
        unfiltered.forEach(
            (T a) -> {
              if (retainIfTrue.test(a)) {
                action.accept(a);
              }
            });
      }

      @Override
      public Spliterator<T> spliterator() {
        return CollectSpliterators.filter(unfiltered.spliterator(), retainIfTrue);
      }
    };
  }

  /**
   * Returns a view of {@code unfiltered} containing all elements that are of the type {@code
   * desiredType}. The returned iterable's iterator does not support {@code remove()}.
   *
   *
{@code Stream} equivalent: {@code stream.filter(type::isInstance).map(type::cast)}.
   * This does perform a little more work than necessary, so another option is to insert an
   * unchecked cast at some later point:
   *
   *

   * {@code @SuppressWarnings("unchecked") // safe because of ::isInstance check
   * ImmutableList<NewType> result =
   *     (ImmutableList) stream.filter(NewType.class::isInstance).collect(toImmutableList());}
   *

   */
  @SuppressWarnings("unchecked")
  @GwtIncompatible // Class.isInstance
  public static <T> Iterable<T> filter(final Iterable<?> unfiltered, final Class<T> desiredType) {
    checkNotNull(unfiltered);
    checkNotNull(desiredType);
    return (Iterable<T>) filter(unfiltered, Predicates.instanceOf(desiredType));
  }

  /**
   * Returns {@code true} if any element in {@code iterable} satisfies the predicate.
   *
   *
{@code Stream} equivalent: {@link Stream#anyMatch}.
   */
  public static <T> boolean any(Iterable<T> iterable, Predicate<? super T> predicate) {
    return Iterators.any(iterable.iterator(), predicate);
  }

  /**
   * Returns {@code true} if every element in {@code iterable} satisfies the predicate. If {@code
   * iterable} is empty, {@code true} is returned.
   *
   *
{@code Stream} equivalent: {@link Stream#allMatch}.
   */
  public static <T> boolean all(Iterable<T> iterable, Predicate<? super T> predicate) {
    return Iterators.all(iterable.iterator(), predicate);
  }

  /**
   * Returns the first element in {@code iterable} that satisfies the given predicate; use this
   * method only when such an element is known to exist. If it is possible that no element
   * will match, use {@link #tryFind} or {@link #find(Iterable, Predicate, Object)} instead.
   *
   *
{@code Stream} equivalent: {@code stream.filter(predicate).findFirst().get()}
   *
   * @throws NoSuchElementException if no element in {@code iterable} matches the given predicate
   */
  public static <T> T find(Iterable<T> iterable, Predicate<? super T> predicate) {
    return Iterators.find(iterable.iterator(), predicate);
  }

  /**
   * Returns the first element in {@code iterable} that satisfies the given predicate, or {@code
   * defaultValue} if none found. Note that this can usually be handled more naturally using {@code
   * tryFind(iterable, predicate).or(defaultValue)}.
   *
   *
{@code Stream} equivalent: {@code
   * stream.filter(predicate).findFirst().orElse(defaultValue)}
   *
   * @since 7.0
   */
  public static <T> @Nullable T find(
      Iterable<? extends T> iterable, Predicate<? super T> predicate, @Nullable T defaultValue) {
    return Iterators.find(iterable.iterator(), predicate, defaultValue);
  }

  /**
   * Returns an {@link Optional} containing the first element in {@code iterable} that satisfies the
   * given predicate, if such an element exists.
   *
   *
Warning: avoid using a {@code predicate} that matches {@code null}. If {@code null}
   * is matched in {@code iterable}, a NullPointerException will be thrown.
   *
   *
{@code Stream} equivalent: {@code stream.filter(predicate).findFirst()}
   *
   * @since 11.0
   */
  public static <T> Optional<T> tryFind(Iterable<T> iterable, Predicate<? super T> predicate) {
    return Iterators.tryFind(iterable.iterator(), predicate);
  }

  /**
   * Returns the index in {@code iterable} of the first element that satisfies the provided {@code
   * predicate}, or {@code -1} if the Iterable has no such elements.
   *
   *
More formally, returns the lowest index {@code i} such that {@code
   * predicate.apply(Iterables.get(iterable, i))} returns {@code true}, or {@code -1} if there is no
   * such index.
   *
   * @since 2.0
   */
  public static <T> int indexOf(Iterable<T> iterable, Predicate<? super T> predicate) {
    return Iterators.indexOf(iterable.iterator(), predicate);
  }

  /**
   * Returns a view containing the result of applying {@code function} to each element of {@code
   * fromIterable}.
   *
   *
The returned iterable's iterator supports {@code remove()} if {@code fromIterable}'s
   * iterator does. After a successful {@code remove()} call, {@code fromIterable} no longer
   * contains the corresponding element.
   *
   *
If the input {@code Iterable} is known to be a {@code List} or other {@code Collection},
   * consider {@link Lists#transform} and {@link Collections2#transform}.
   *
   *
{@code Stream} equivalent: {@link Stream#map}
   */
  public static <F, T> Iterable<T> transform(
      final Iterable<F> fromIterable, final Function<? super F, ? extends T> function) {
    checkNotNull(fromIterable);
    checkNotNull(function);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.transform(fromIterable.iterator(), function);
      }

      @Override
      public void forEach(Consumer<? super T> action) {
        checkNotNull(action);
        fromIterable.forEach((F f) -> action.accept(function.apply(f)));
      }

      @Override
      public Spliterator<T> spliterator() {
        return CollectSpliterators.map(fromIterable.spliterator(), function);
      }
    };
  }

  /**
   * Returns the element at the specified position in an iterable.
   *
   *
{@code Stream} equivalent: {@code stream.skip(position).findFirst().get()} (throws
   * {@code NoSuchElementException} if out of bounds)
   *
   * @param position position of the element to return
   * @return the element at the specified position in {@code iterable}
   * @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to
   *     the size of {@code iterable}
   */
  public static <T> T get(Iterable<T> iterable, int position) {
    checkNotNull(iterable);
    return (iterable instanceof List)
        ? ((List<T>) iterable).get(position)
        : Iterators.get(iterable.iterator(), position);
  }

  /**
   * Returns the element at the specified position in an iterable or a default value otherwise.
   *
   *
{@code Stream} equivalent: {@code
   * stream.skip(position).findFirst().orElse(defaultValue)} (returns the default value if the index
   * is out of bounds)
   *
   * @param position position of the element to return
   * @param defaultValue the default value to return if {@code position} is greater than or equal to
   *     the size of the iterable
   * @return the element at the specified position in {@code iterable} or {@code defaultValue} if
   *     {@code iterable} contains fewer than {@code position + 1} elements.
   * @throws IndexOutOfBoundsException if {@code position} is negative
   * @since 4.0
   */
  public static <T> @Nullable T get(
      Iterable<? extends T> iterable, int position, @Nullable T defaultValue) {
    checkNotNull(iterable);
    Iterators.checkNonnegative(position);
    if (iterable instanceof List) {
      List<? extends T> list = Lists.cast(iterable);
      return (position < list.size()) ? list.get(position) : defaultValue;
    } else {
      Iterator<? extends T> iterator = iterable.iterator();
      Iterators.advance(iterator, position);
      return Iterators.getNext(iterator, defaultValue);
    }
  }

  /**
   * Returns the first element in {@code iterable} or {@code defaultValue} if the iterable is empty.
   * The {@link Iterators} analog to this method is {@link Iterators#getNext}.
   *
   *
If no default value is desired (and the caller instead wants a {@link
   * NoSuchElementException} to be thrown), it is recommended that {@code
   * iterable.iterator().next()} is used instead.
   *
   *
To get the only element in a single-element {@code Iterable}, consider using {@link
   * #getOnlyElement(Iterable)} or {@link #getOnlyElement(Iterable, Object)} instead.
   *
   *
{@code Stream} equivalent: {@code stream.findFirst().orElse(defaultValue)}
   *
   * @param defaultValue the default value to return if the iterable is empty
   * @return the first element of {@code iterable} or the default value
   * @since 7.0
   */
  public static <T> @Nullable T getFirst(Iterable<? extends T> iterable, @Nullable T defaultValue) {
    return Iterators.getNext(iterable.iterator(), defaultValue);
  }

  /**
   * Returns the last element of {@code iterable}. If {@code iterable} is a {@link List} with {@link
   * RandomAccess} support, then this operation is guaranteed to be {@code O(1)}.
   *
   *
{@code Stream} equivalent: {@link Streams#findLast Streams.findLast(stream).get()}
   *
   * @return the last element of {@code iterable}
   * @throws NoSuchElementException if the iterable is empty
   */
  public static <T> T getLast(Iterable<T> iterable) {
    // TODO(kevinb): Support a concurrently modified collection?
    if (iterable instanceof List) {
      List<T> list = (List<T>) iterable;
      if (list.isEmpty()) {
        throw new NoSuchElementException();
      }
      return getLastInNonemptyList(list);
    }

    return Iterators.getLast(iterable.iterator());
  }

  /**
   * Returns the last element of {@code iterable} or {@code defaultValue} if the iterable is empty.
   * If {@code iterable} is a {@link List} with {@link RandomAccess} support, then this operation is
   * guaranteed to be {@code O(1)}.
   *
   *
{@code Stream} equivalent: {@code Streams.findLast(stream).orElse(defaultValue)}
   *
   * @param defaultValue the value to return if {@code iterable} is empty
   * @return the last element of {@code iterable} or the default value
   * @since 3.0
   */
  public static <T> @Nullable T getLast(Iterable<? extends T> iterable, @Nullable T defaultValue) {
    if (iterable instanceof Collection) {
      Collection<? extends T> c = Collections2.cast(iterable);
      if (c.isEmpty()) {
        return defaultValue;
      } else if (iterable instanceof List) {
        return getLastInNonemptyList(Lists.cast(iterable));
      }
    }

    return Iterators.getLast(iterable.iterator(), defaultValue);
  }

  private static <T> T getLastInNonemptyList(List<T> list) {
    return list.get(list.size() - 1);
  }

  /**
   * Returns a view of {@code iterable} that skips its first {@code numberToSkip} elements. If
   * {@code iterable} contains fewer than {@code numberToSkip} elements, the returned iterable skips
   * all of its elements.
   *
   *
Modifications to the underlying {@link Iterable} before a call to {@code iterator()} are
   * reflected in the returned iterator. That is, the iterator skips the first {@code numberToSkip}
   * elements that exist when the {@code Iterator} is created, not when {@code skip()} is called.
   *
   *
The returned iterable's iterator supports {@code remove()} if the iterator of the underlying
   * iterable supports it. Note that it is not possible to delete the last skipped element by
   * immediately calling {@code remove()} on that iterator, as the {@code Iterator} contract states
   * that a call to {@code remove()} before a call to {@code next()} will throw an {@link
   * IllegalStateException}.
   *
   *
{@code Stream} equivalent: {@link Stream#skip}
   *
   * @since 3.0
   */
  public static <T> Iterable<T> skip(final Iterable<T> iterable, final int numberToSkip) {
    checkNotNull(iterable);
    checkArgument(numberToSkip >= 0, "number to skip cannot be negative");

    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        if (iterable instanceof List) {
          final List<T> list = (List<T>) iterable;
          int toSkip = Math.min(list.size(), numberToSkip);
          return list.subList(toSkip, list.size()).iterator();
        }
        final Iterator<T> iterator = iterable.iterator();

        Iterators.advance(iterator, numberToSkip);

        /*
         * We can't just return the iterator because an immediate call to its
         * remove() method would remove one of the skipped elements instead of
         * throwing an IllegalStateException.
         */
        return new Iterator<T>() {
          boolean atStart = true;

          @Override
          public boolean hasNext() {
            return iterator.hasNext();
          }

          @Override
          public T next() {
            T result = iterator.next();
            atStart = false; // not called if next() fails
            return result;
          }

          @Override
          public void remove() {
            checkRemove(!atStart);
            iterator.remove();
          }
        };
      }

      @Override
      public Spliterator<T> spliterator() {
        if (iterable instanceof List) {
          final List<T> list = (List<T>) iterable;
          int toSkip = Math.min(list.size(), numberToSkip);
          return list.subList(toSkip, list.size()).spliterator();
        } else {
          return Streams.stream(iterable).skip(numberToSkip).spliterator();
        }
      }
    };
  }

  /**
   * Returns a view of {@code iterable} containing its first {@code limitSize} elements. If {@code
   * iterable} contains fewer than {@code limitSize} elements, the returned view contains all of its
   * elements. The returned iterable's iterator supports {@code remove()} if {@code iterable}'s
   * iterator does.
   *
   *
{@code Stream} equivalent: {@link Stream#limit}
   *
   * @param iterable the iterable to limit
   * @param limitSize the maximum number of elements in the returned iterable
   * @throws IllegalArgumentException if {@code limitSize} is negative
   * @since 3.0
   */
  public static <T> Iterable<T> limit(final Iterable<T> iterable, final int limitSize) {
    checkNotNull(iterable);
    checkArgument(limitSize >= 0, "limit is negative");
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.limit(iterable.iterator(), limitSize);
      }

      @Override
      public Spliterator<T> spliterator() {
        return Streams.stream(iterable).limit(limitSize).spliterator();
      }
    };
  }

  /**
   * Returns a view of the supplied iterable that wraps each generated {@link Iterator} through
   * {@link Iterators#consumingIterator(Iterator)}.
   *
   *
Note: If {@code iterable} is a {@link Queue}, the returned iterable will get entries from
   * {@link Queue#remove()} since {@link Queue}'s iteration order is undefined. Calling {@link
   * Iterator#hasNext()} on a generated iterator from the returned iterable may cause an item to be
   * immediately dequeued for return on a subsequent call to {@link Iterator#next()}.
   *
   * @param iterable the iterable to wrap
   * @return a view of the supplied iterable that wraps each generated iterator through {@link
   *     Iterators#consumingIterator(Iterator)}; for queues, an iterable that generates iterators
   *     that return and consume the queue's elements in queue order
   * @see Iterators#consumingIterator(Iterator)
   * @since 2.0
   */
  public static <T> Iterable<T> consumingIterable(final Iterable<T> iterable) {
    checkNotNull(iterable);

    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return (iterable instanceof Queue)
            ? new ConsumingQueueIterator<>((Queue<T>) iterable)
            : Iterators.consumingIterator(iterable.iterator());
      }

      @Override
      public String toString() {
        return "Iterables.consumingIterable(...)";
      }
    };
  }

  // Methods only in Iterables, not in Iterators

  /**
   * Determines if the given iterable contains no elements.
   *
   *
There is no precise {@link Iterator} equivalent to this method, since one can only ask an
   * iterator whether it has any elements remaining (which one does using {@link
   * Iterator#hasNext}).
   *
   *
{@code Stream} equivalent: {@code !stream.findAny().isPresent()}
   *
   * @return {@code true} if the iterable contains no elements
   */
  public static boolean isEmpty(Iterable<?> iterable) {
    if (iterable instanceof Collection) {
      return ((Collection<?>) iterable).isEmpty();
    }
    return !iterable.iterator().hasNext();
  }

  /**
   * Returns an iterable over the merged contents of all given {@code iterables}. Equivalent entries
   * will not be de-duplicated.
   *
   *
Callers must ensure that the source {@code iterables} are in non-descending order as this
   * method does not sort its input.
   *
   *
For any equivalent elements across all {@code iterables}, it is undefined which element is
   * returned first.
   *
   * @since 11.0
   */
  @Beta
  public static <T> Iterable<T> mergeSorted(
      final Iterable<? extends Iterable<? extends T>> iterables,
      final Comparator<? super T> comparator) {
    checkNotNull(iterables, "iterables");
    checkNotNull(comparator, "comparator");
    Iterable<T> iterable =
        new FluentIterable<T>() {
          @Override
          public Iterator<T> iterator() {
            return Iterators.mergeSorted(
                Iterables.transform(iterables, Iterables.<T>toIterator()), comparator);
          }
        };
    return new UnmodifiableIterable<>(iterable);
  }

  // TODO(user): Is this the best place for this? Move to fluent functions?
  // Useful as a public method?
  static <T> Function<Iterable<? extends T>, Iterator<? extends T>> toIterator() {
    return new Function<Iterable<? extends T>, Iterator<? extends T>>() {
      @Override
      public Iterator<? extends T> apply(Iterable<? extends T> iterable) {
        return iterable.iterator();
      }
    };
  }
}


/*
 * Copyright (C) 2015 The Guava Authors
 *
 * 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.hash;

import com.google.common.primitives.Longs;
import java.nio.ByteOrder;
import sun.misc.Unsafe;

/**
 * Utility functions for loading and storing values from a byte array.
 *
 * @author Kevin Damm
 * @author Kyle Maddison
 */
final class LittleEndianByteArray {

  /** The instance that actually does the work; delegates to Unsafe or a pure-Java fallback. */
  private static final LittleEndianBytes byteArray;

  /**
   * Load 8 bytes into long in a little endian manner, from the substring between position and
   * position + 8. The array must have at least 8 bytes from offset (inclusive).
   *
   * @param input the input bytes
   * @param offset the offset into the array at which to start
   * @return a long of a concatenated 8 bytes
   */
  static long load64(byte[] input, int offset) {
    // We don't want this in production code as this is the most critical part of the loop.
    assert input.length >= offset + 8;
    // Delegates to the fast (unsafe) version or the fallback.
    return byteArray.getLongLittleEndian(input, offset);
  }

  /**
   * Similar to load64, but allows offset + 8 > input.length, padding the result with zeroes. This
   * has to explicitly reverse the order of the bytes as it packs them into the result which makes
   * it slower than the native version.
   *
   * @param input the input bytes
   * @param offset the offset into the array at which to start reading
   * @param length the number of bytes from the input to read
   * @return a long of a concatenated 8 bytes
   */
  static long load64Safely(byte[] input, int offset, int length) {
    long result = 0;
    // Due to the way we shift, we can stop iterating once we've run out of data, the rest
    // of the result already being filled with zeros.

    // This loop is critical to performance, so please check HashBenchmark if altering it.
    int limit = Math.min(length, 8);
    for (int i = 0; i < limit; i++) {
      // Shift value left while iterating logically through the array.
      result |= (input[offset + i] & 0xFFL) << (i * 8);
    }
    return result;
  }

  /**
   * Store 8 bytes into the provided array at the indicated offset, using the value provided.
   *
   * @param sink the output byte array
   * @param offset the offset into the array at which to start writing
   * @param value the value to write
   */
  static void store64(byte[] sink, int offset, long value) {
    // We don't want to assert in production code.
    assert offset >= 0 && offset + 8 <= sink.length;
    // Delegates to the fast (unsafe)version or the fallback.
    byteArray.putLongLittleEndian(sink, offset, value);
  }

  /**
   * Load 4 bytes from the provided array at the indicated offset.
   *
   * @param source the input bytes
   * @param offset the offset into the array at which to start
   * @return the value found in the array in the form of a long
   */
  static int load32(byte[] source, int offset) {
    // TODO(user): Measure the benefit of delegating this to LittleEndianBytes also.
    return (source[offset] & 0xFF)
        | ((source[offset + 1] & 0xFF) << 8)
        | ((source[offset + 2] & 0xFF) << 16)
        | ((source[offset + 3] & 0xFF) << 24);
  }

  /**
   * Indicates that the loading of Unsafe was successful and the load and store operations will be
   * very efficient. May be useful for calling code to fall back on an alternative implementation
   * that is slower than Unsafe.get/store but faster than the pure-Java mask-and-shift.
   */
  static boolean usingUnsafe() {
    return (byteArray instanceof UnsafeByteArray);
  }

  /**
   * Common interface for retrieving a 64-bit long from a little-endian byte array.
   *
   * <p>This abstraction allows us to use single-instruction load and put when available, or fall
   * back on the slower approach of using Longs.fromBytes(byte...).
   */
  private interface LittleEndianBytes {
    long getLongLittleEndian(byte[] array, int offset);

    void putLongLittleEndian(byte[] array, int offset, long value);
  }

  /**
   * The only reference to Unsafe is in this nested class. We set things up so that if
   * Unsafe.theUnsafe is inaccessible, the attempt to load the nested class fails, and the outer
   * class's static initializer can fall back on a non-Unsafe version.
   */
  private enum UnsafeByteArray implements LittleEndianBytes {
    // Do *not* change the order of these constants!
    UNSAFE_LITTLE_ENDIAN {
      @Override
      public long getLongLittleEndian(byte[] array, int offset) {
        return theUnsafe.getLong(array, (long) offset + BYTE_ARRAY_BASE_OFFSET);
      }

      @Override
      public void putLongLittleEndian(byte[] array, int offset, long value) {
        theUnsafe.putLong(array, (long) offset + BYTE_ARRAY_BASE_OFFSET, value);
      }
    },
    UNSAFE_BIG_ENDIAN {
      @Override
      public long getLongLittleEndian(byte[] array, int offset) {
        long bigEndian = theUnsafe.getLong(array, (long) offset + BYTE_ARRAY_BASE_OFFSET);
        // The hardware is big-endian, so we need to reverse the order of the bytes.
        return Long.reverseBytes(bigEndian);
      }

      @Override
      public void putLongLittleEndian(byte[] array, int offset, long value) {
        // Reverse the order of the bytes before storing, since we're on big-endian hardware.
        long littleEndianValue = Long.reverseBytes(value);
        theUnsafe.putLong(array, (long) offset + BYTE_ARRAY_BASE_OFFSET, littleEndianValue);
      }
    };

    // Provides load and store operations that use native instructions to get better performance.
    private static final Unsafe theUnsafe;

    // The offset to the first element in a byte array.
    private static final int BYTE_ARRAY_BASE_OFFSET;

    /**
     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. Replace with a simple
     * call to Unsafe.getUnsafe when integrating into a jdk.
     *
     * @return a sun.misc.Unsafe instance if successful
     */
    private static sun.misc.Unsafe getUnsafe() {
      try {
        return sun.misc.Unsafe.getUnsafe();
      } catch (SecurityException tryReflectionInstead) {
        // We'll try reflection instead.
      }
      try {
        return java.security.AccessController.doPrivileged(
            new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
              @Override
              public sun.misc.Unsafe run() throws Exception {
                Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
                for (java.lang.reflect.Field f : k.getDeclaredFields()) {
                  f.setAccessible(true);
                  Object x = f.get(null);
                  if (k.isInstance(x)) {
                    return k.cast(x);
                  }
                }
                throw new NoSuchFieldError("the Unsafe");
              }
            });
      } catch (java.security.PrivilegedActionException e) {
        throw new RuntimeException("Could not initialize intrinsics", e.getCause());
      }
    }

    static {
      theUnsafe = getUnsafe();
      BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);

      // sanity check - this should never fail
      if (theUnsafe.arrayIndexScale(byte[].class) != 1) {
        throw new AssertionError();
      }
    }
  }

  /** Fallback implementation for when Unsafe is not available in our current environment. */
  private enum JavaLittleEndianBytes implements LittleEndianBytes {
    INSTANCE {
      @Override
      public long getLongLittleEndian(byte[] source, int offset) {
        return Longs.fromBytes(
            source[offset + 7],
            source[offset + 6],
            source[offset + 5],
            source[offset + 4],
            source[offset + 3],
            source[offset + 2],
            source[offset + 1],
            source[offset]);
      }

      @Override
      public void putLongLittleEndian(byte[] sink, int offset, long value) {
        long mask = 0xFFL;
        for (int i = 0; i < 8; mask <<= 8, i++) {
          sink[offset + i] = (byte) ((value & mask) >> (i * 8));
        }
      }
    };
  }

  static {
    LittleEndianBytes theGetter = JavaLittleEndianBytes.INSTANCE;
    try {
      /*
        UnsafeByteArray uses Unsafe.getLong() in an unsupported way, which is known to cause crashes
        on Android when running in 32-bit mode. For maximum safety, we shouldn't use
        Unsafe.getLong() at all, but the performance benefit on x86_64 is too great to ignore, so as
        a compromise, we enable the optimization only on platforms that we specifically know to
        work.

        In the future, the use of Unsafe.getLong() should be replaced by ByteBuffer.getLong(), which
        will have an efficient native implementation in JDK 9.

      */
      final String arch = System.getProperty("os.arch");
      if ("amd64".equals(arch)) {
        theGetter =
            ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)
                ? UnsafeByteArray.UNSAFE_LITTLE_ENDIAN
                : UnsafeByteArray.UNSAFE_BIG_ENDIAN;
      }
    } catch (Throwable t) {
      // ensure we really catch *everything*
    }
    byteArray = theGetter;
  }

  /** Deter instantiation of this class. */
  private LittleEndianByteArray() {}
}


/*
 * Copyright (C) 2009 The Guava Authors
 *
 * 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.util.concurrent;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Supplier;
import java.util.concurrent.Callable;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Static utility methods pertaining to the {@link Callable} interface.
 *
 * @author Isaac Shum
 * @since 1.0
 */
@GwtCompatible(emulated = true)
public final class Callables {
  private Callables() {}

  /** Creates a {@code Callable} which immediately returns a preset value each time it is called. */
  public static <T> Callable<T> returning(final @Nullable T value) {
    return new Callable<T>() {
      @Override
      public T call() {
        return value;
      }
    };
  }

  /**
   * Creates an {@link AsyncCallable} from a {@link Callable}.
   *
   * <p>The {@link AsyncCallable} returns the {@link ListenableFuture} resulting from {@link
   * ListeningExecutorService#submit(Callable)}.
   *
   * @since 20.0
   */
  @Beta
  @GwtIncompatible
  public static <T> AsyncCallable<T> asAsyncCallable(
      final Callable<T> callable, final ListeningExecutorService listeningExecutorService) {
    checkNotNull(callable);
    checkNotNull(listeningExecutorService);
    return new AsyncCallable<T>() {
      @Override
      public ListenableFuture<T> call() throws Exception {
        return listeningExecutorService.submit(callable);
      }
    };
  }

  /**
   * Wraps the given callable such that for the duration of {@link Callable#call} the thread that is
   * running will have the given name.
   *
   *
   * @param callable The callable to wrap
   * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
   *     for each invocation of the wrapped callable.
   */
  @GwtIncompatible // threads
  static <T> Callable<T> threadRenaming(
      final Callable<T> callable, final Supplier<String> nameSupplier) {
    checkNotNull(nameSupplier);
    checkNotNull(callable);
    return new Callable<T>() {
      @Override
      public T call() throws Exception {
        Thread currentThread = Thread.currentThread();
        String oldName = currentThread.getName();
        boolean restoreName = trySetName(nameSupplier.get(), currentThread);
        try {
          return callable.call();
        } finally {
          if (restoreName) {
            boolean unused = trySetName(oldName, currentThread);
          }
        }
      }
    };
  }

  /**
   * Wraps the given runnable such that for the duration of {@link Runnable#run} the thread that is
   * running with have the given name.
   *
   *
   * @param task The Runnable to wrap
   * @param nameSupplier The supplier of thread names, {@link Supplier#get get} will be called once
   *     for each invocation of the wrapped callable.
   */
  @GwtIncompatible // threads
  static Runnable threadRenaming(final Runnable task, final Supplier<String> nameSupplier) {
    checkNotNull(nameSupplier);
    checkNotNull(task);
    return new Runnable() {
      @Override
      public void run() {
        Thread currentThread = Thread.currentThread();
        String oldName = currentThread.getName();
        boolean restoreName = trySetName(nameSupplier.get(), currentThread);
        try {
          task.run();
        } finally {
          if (restoreName) {
            boolean unused = trySetName(oldName, currentThread);
          }
        }
      }
    };
  }

  /** Tries to set name of the given {@link Thread}, returns true if successful. */
  @GwtIncompatible // threads
  private static boolean trySetName(final String threadName, Thread currentThread) {
    // In AppEngine, this will always fail. Should we test for that explicitly using
    // MoreExecutors.isAppEngine? More generally, is there a way to see if we have the modifyThread
    // permission without catching an exception?
    try {
      currentThread.setName(threadName);
      return true;
    } catch (SecurityException e) {
      return false;
    }
  }
}


/*
 * Copyright (C) 2011 The Guava Authors
 *
 * 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.collect;

import com.google.common.annotations.GwtIncompatible;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.stream.Collector;

/**
 * "Overrides" the {@link ImmutableMultiset} static methods that lack {@link
 * ImmutableSortedMultiset} equivalents with deprecated, exception-throwing versions. This prevents
 * accidents like the following:
 *
 *
{@code
 * List<Object> objects = ...;
 * // Sort them:
 * Set<Object> sorted = ImmutableSortedMultiset.copyOf(objects);
 * // BAD CODE! The returned multiset is actually an unsorted ImmutableMultiset!
 * }

 *
 *
While we could put the overrides in {@link ImmutableSortedMultiset} itself, it seems clearer
 * to separate these "do not call" methods from those intended for normal use.
 *
 * @author Louis Wasserman
 */
@GwtIncompatible
abstract class ImmutableSortedMultisetFauxverideShim<E> extends ImmutableMultiset<E> {
  /**
   * Not supported. Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset} instead. This
   * method exists only to hide {@link ImmutableMultiset#toImmutableMultiset} from consumers of
   * {@code ImmutableSortedMultiset}.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}.
   * @since 21.0
   */
  @Deprecated
  public static <E> Collector<E, ?, ImmutableMultiset<E>> toImmutableMultiset() {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset} instead. This
   * method exists only to hide {@link ImmutableMultiset#toImmutableMultiset} from consumers of
   * {@code ImmutableSortedMultiset}.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}.
   * @since 22.0
   */
  @Deprecated
  public static <T, E> Collector<T, ?, ImmutableMultiset<E>> toImmutableMultiset(
      Function<? super T, ? extends E> elementFunction, ToIntFunction<? super T> countFunction) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. Use {@link ImmutableSortedMultiset#naturalOrder}, which offers better
   * type-safety, instead. This method exists only to hide {@link ImmutableMultiset#builder} from
   * consumers of {@code ImmutableSortedMultiset}.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Use {@link ImmutableSortedMultiset#naturalOrder}, which offers better type-safety.
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset.Builder<E> builder() {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain a non-{@code
   * Comparable} element. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass a parameter of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#of(Comparable)}.
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> of(E element) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain a non-{@code
   * Comparable} element. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass the parameters of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#of(Comparable, Comparable)}.
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain a non-{@code
   * Comparable} element. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass the parameters of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable)}.
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain a non-{@code
   * Comparable} element. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass the parameters of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable)}.
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain a non-{@code
   * Comparable} element. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass the parameters of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable)} .
   *
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain a non-{@code
   * Comparable} element. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass the parameters of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable,
   *     Comparable, Comparable...)} .
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> of(
      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
    throw new UnsupportedOperationException();
  }

  /**
   * Not supported. You are attempting to create a multiset that may contain non-{@code
   * Comparable} elements. Proper calls will resolve to the version in {@code
   * ImmutableSortedMultiset}, not this dummy version.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Pass parameters of type {@code Comparable} to use {@link
   *     ImmutableSortedMultiset#copyOf(Comparable[])}.
   */
  @Deprecated
  public static <E> ImmutableSortedMultiset<E> copyOf(E[] elements) {
    throw new UnsupportedOperationException();
  }

  /*
   * We would like to include an unsupported "<E> copyOf(Iterable<E>)" here, providing only the
   * properly typed "<E extends Comparable<E>> copyOf(Iterable<E>)" in ImmutableSortedMultiset (and
   * likewise for the Iterator equivalent). However, due to a change in Sun's interpretation of the
   * JLS (as described at http://bugs.sun.com/view_bug.do?bug_id=6182950), the OpenJDK 7 compiler
   * available as of this writing rejects our attempts. To maintain compatibility with that version
   * and with any other compilers that interpret the JLS similarly, there is no definition of
   * copyOf() here, and the definition in ImmutableSortedMultiset matches that in
   * ImmutableMultiset.
   *
   * The result is that ImmutableSortedMultiset.copyOf() may be called on non-Comparable elements.
   * We have not discovered a better solution. In retrospect, the static factory methods should
   * have gone in a separate class so that ImmutableSortedMultiset wouldn't "inherit"
   * too-permissive factory methods from ImmutableMultiset.
   */
}


/*
 * Copyright (C) 2006 The Guava Authors
 *
 * 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.util.concurrent;

import com.google.common.base.Function;
import java.util.concurrent.Executor;

/**
 * Hidden superclass of {@link FluentFuture} that provides us a place to declare special GWT
 * versions of the {@link FluentFuture#catching(Class, com.google.common.base.Function)
 * FluentFuture.catching} family of methods. Those versions have slightly different signatures.
 */
abstract class GwtFluentFutureCatchingSpecialization<V> extends AbstractFuture<V> {
  /*
   * In the GWT versions of the methods (below), every exceptionType parameter is required to be
   * Class<Throwable>. To handle only certain kinds of exceptions under GWT, you'll need to write
   * your own instanceof tests.
   */

  public final FluentFuture<V> catching(
      Class<Throwable> exceptionType,
      Function<? super Throwable, ? extends V> fallback,
      Executor executor) {
    return (FluentFuture<V>) Futures.catching(this, exceptionType, fallback, executor);
  }

  public final FluentFuture<V> catchingAsync(
      Class<Throwable> exceptionType,
      AsyncFunction<? super Throwable, ? extends V> fallback,
      Executor executor) {
    return (FluentFuture<V>) Futures.catchingAsync(this, exceptionType, fallback, executor);
  }
}