/*
 * 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 com.google.common.annotations.GwtCompatible;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * Basic implementation of the {@link SetMultimap} interface. It's a wrapper around {@link
 * AbstractMapBasedMultimap} that converts the returned collections into {@code Sets}. The {@link
 * #createCollection} method must return a {@code Set}.
 *
 * @author Jared Levy
 */
@GwtCompatible
abstract class AbstractSetMultimap<K, V> extends AbstractMapBasedMultimap<K, V>
    implements SetMultimap<K, V> {
  /**
   * Creates a new multimap that uses the provided map.
   *
   * @param map place to store the mapping from each key to its corresponding values
   */
  protected AbstractSetMultimap(Map<K, Collection<V>> map) {
    super(map);
  }

  @Override
  abstract Set<V> createCollection();

  @Override
  Set<V> createUnmodifiableEmptyCollection() {
    return Collections.emptySet();
  }

  @Override
  <E> Collection<E> unmodifiableCollectionSubclass(Collection<E> collection) {
    return Collections.unmodifiableSet((Set<E>) collection);
  }

  @Override
  Collection<V> wrapCollection(K key, Collection<V> collection) {
    return new WrappedSet(key, (Set<V>) collection);
  }

  // Following Javadoc copied from SetMultimap.

  /**
   * {@inheritDoc}
   *
   *
Because a {@code SetMultimap} has unique values for a given key, this method returns a
   * {@link Set}, instead of the {@link Collection} specified in the {@link Multimap} interface.
   */
  @Override
  public Set<V> get(@NullableDecl K key) {
    return (Set<V>) super.get(key);
  }

  /**
   * {@inheritDoc}
   *
   *
Because a {@code SetMultimap} has unique values for a given key, this method returns a
   * {@link Set}, instead of the {@link Collection} specified in the {@link Multimap} interface.
   */
  @Override
  public Set<Entry<K, V>> entries() {
    return (Set<Entry<K, V>>) super.entries();
  }

  /**
   * {@inheritDoc}
   *
   *
Because a {@code SetMultimap} has unique values for a given key, this method returns a
   * {@link Set}, instead of the {@link Collection} specified in the {@link Multimap} interface.
   */
  @CanIgnoreReturnValue
  @Override
  public Set<V> removeAll(@NullableDecl Object key) {
    return (Set<V>) super.removeAll(key);
  }

  /**
   * {@inheritDoc}
   *
   *
Because a {@code SetMultimap} has unique values for a given key, this method returns a
   * {@link Set}, instead of the {@link Collection} specified in the {@link Multimap} interface.
   *
   *
Any duplicates in {@code values} will be stored in the multimap once.
   */
  @CanIgnoreReturnValue
  @Override
  public Set<V> replaceValues(@NullableDecl K key, Iterable<? extends V> values) {
    return (Set<V>) super.replaceValues(key, values);
  }

  /**
   * {@inheritDoc}
   *
   *
Though the method signature doesn't say so explicitly, the returned map has {@link Set}
   * values.
   */
  @Override
  public Map<K, Collection<V>> asMap() {
    return super.asMap();
  }

  /**
   * Stores a key-value pair in the multimap.
   *
   * @param key key to store in the multimap
   * @param value value to store in the multimap
   * @return {@code true} if the method increased the size of the multimap, or {@code false} if the
   *     multimap already contained the key-value pair
   */
  @CanIgnoreReturnValue
  @Override
  public boolean put(@NullableDecl K key, @NullableDecl V value) {
    return super.put(key, value);
  }

  /**
   * Compares the specified object to this multimap for equality.
   *
   *
Two {@code SetMultimap} instances are equal if, for each key, they contain the same values.
   * Equality does not depend on the ordering of keys or values.
   */
  @Override
  public boolean equals(@NullableDecl Object object) {
    return super.equals(object);
  }

  private static final long serialVersionUID = 7431625294878419160L;
}


/*
 * 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.collect;

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

import com.google.common.annotations.GwtCompatible;
import com.google.j2objc.annotations.WeakOuter;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * An implementation of {@link ImmutableTable} holding an arbitrary number of cells.
 *
 * @author Gregory Kick
 */
@GwtCompatible
abstract class RegularImmutableTable<R, C, V> extends ImmutableTable<R, C, V> {
  RegularImmutableTable() {}

  abstract Cell<R, C, V> getCell(int iterationIndex);

  @Override
  final ImmutableSet<Cell<R, C, V>> createCellSet() {
    return isEmpty() ? ImmutableSet.<Cell<R, C, V>>of() : new CellSet();
  }

  @WeakOuter
  private final class CellSet extends IndexedImmutableSet<Cell<R, C, V>> {
    @Override
    public int size() {
      return RegularImmutableTable.this.size();
    }

    @Override
    Cell<R, C, V> get(int index) {
      return getCell(index);
    }

    @Override
    public boolean contains(@NullableDecl Object object) {
      if (object instanceof Cell) {
        Cell<?, ?, ?> cell = (Cell<?, ?, ?>) object;
        Object value = RegularImmutableTable.this.get(cell.getRowKey(), cell.getColumnKey());
        return value != null && value.equals(cell.getValue());
      }
      return false;
    }

    @Override
    boolean isPartialView() {
      return false;
    }
  }

  abstract V getValue(int iterationIndex);

  @Override
  final ImmutableCollection<V> createValues() {
    return isEmpty() ? ImmutableList.<V>of() : new Values();
  }

  @WeakOuter
  private final class Values extends ImmutableList<V> {
    @Override
    public int size() {
      return RegularImmutableTable.this.size();
    }

    @Override
    public V get(int index) {
      return getValue(index);
    }

    @Override
    boolean isPartialView() {
      return true;
    }
  }

  static <R, C, V> RegularImmutableTable<R, C, V> forCells(
      List<Cell<R, C, V>> cells,
      @NullableDecl final Comparator<? super R> rowComparator,
      @NullableDecl final Comparator<? super C> columnComparator) {
    checkNotNull(cells);
    if (rowComparator != null || columnComparator != null) {
      /*
       * This sorting logic leads to a cellSet() ordering that may not be expected and that isn't
       * documented in the Javadoc. If a row Comparator is provided, cellSet() iterates across the
       * columns in the first row, the columns in the second row, etc. If a column Comparator is
       * provided but a row Comparator isn't, cellSet() iterates across the rows in the first
       * column, the rows in the second column, etc.
       */
      Comparator<Cell<R, C, V>> comparator =
          new Comparator<Cell<R, C, V>>() {
            @Override
            public int compare(Cell<R, C, V> cell1, Cell<R, C, V> cell2) {
              int rowCompare =
                  (rowComparator == null)
                      ? 0
                      : rowComparator.compare(cell1.getRowKey(), cell2.getRowKey());
              if (rowCompare != 0) {
                return rowCompare;
              }
              return (columnComparator == null)
                  ? 0
                  : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey());
            }
          };
      Collections.sort(cells, comparator);
    }
    return forCellsInternal(cells, rowComparator, columnComparator);
  }

  static <R, C, V> RegularImmutableTable<R, C, V> forCells(Iterable<Cell<R, C, V>> cells) {
    return forCellsInternal(cells, null, null);
  }

  private static <R, C, V> RegularImmutableTable<R, C, V> forCellsInternal(
      Iterable<Cell<R, C, V>> cells,
      @NullableDecl Comparator<? super R> rowComparator,
      @NullableDecl Comparator<? super C> columnComparator) {
    Set<R> rowSpaceBuilder = new LinkedHashSet<>();
    Set<C> columnSpaceBuilder = new LinkedHashSet<>();
    ImmutableList<Cell<R, C, V>> cellList = ImmutableList.copyOf(cells);
    for (Cell<R, C, V> cell : cells) {
      rowSpaceBuilder.add(cell.getRowKey());
      columnSpaceBuilder.add(cell.getColumnKey());
    }

    ImmutableSet<R> rowSpace =
        (rowComparator == null)
            ? ImmutableSet.copyOf(rowSpaceBuilder)
            : ImmutableSet.copyOf(ImmutableList.sortedCopyOf(rowComparator, rowSpaceBuilder));
    ImmutableSet<C> columnSpace =
        (columnComparator == null)
            ? ImmutableSet.copyOf(columnSpaceBuilder)
            : ImmutableSet.copyOf(ImmutableList.sortedCopyOf(columnComparator, columnSpaceBuilder));

    return forOrderedComponents(cellList, rowSpace, columnSpace);
  }

  /** A factory that chooses the most space-efficient representation of the table. */
  static <R, C, V> RegularImmutableTable<R, C, V> forOrderedComponents(
      ImmutableList<Cell<R, C, V>> cellList,
      ImmutableSet<R> rowSpace,
      ImmutableSet<C> columnSpace) {
    // use a dense table if more than half of the cells have values
    // TODO(gak): tune this condition based on empirical evidence
    return (cellList.size() > (((long) rowSpace.size() * columnSpace.size()) / 2))
        ? new DenseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace)
        : new SparseImmutableTable<R, C, V>(cellList, rowSpace, columnSpace);
  }

  /** @throws IllegalArgumentException if {@code existingValue} is not null. */
  /*
   * We could have declared this method 'static' but the additional compile-time checks achieved by
   * referencing the type variables seem worthwhile.
   */
  final void checkNoDuplicate(R rowKey, C columnKey, V existingValue, V newValue) {
    checkArgument(
        existingValue == null,
        "Duplicate key: (row=%s, column=%s), values: [%s, %s].",
        rowKey,
        columnKey,
        newValue,
        existingValue);
  }
}


/*
 * 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 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.Function;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * A {@link ListenableFuture} that supports fluent chains of operations. For example:
 *
 *
{@code
 * ListenableFuture<Boolean> adminIsLoggedIn =
 *     FluentFuture.from(usersDatabase.getAdminUser())
 *         .transform(User::getId, directExecutor())
 *         .transform(ActivityService::isLoggedIn, threadPool)
 *         .catching(RpcException.class, e -> false, directExecutor());
 * }

 *
 *
Alternatives

 *
 *
Frameworks

 *
 *
When chaining together a graph of asynchronous operations, you will often find it easier to
 * use a framework. Frameworks automate the process, often adding features like monitoring,
 * debugging, and cancellation. Examples of frameworks include:
 *
 *

 *
Dagger Producers
 *

 *
 *
{@link java.util.concurrent.CompletableFuture} / {@link java.util.concurrent.CompletionStage}
 *

 *
 *
Users of {@code CompletableFuture} will likely want to continue using {@code
 * CompletableFuture}. {@code FluentFuture} is targeted at people who use {@code ListenableFuture},
 * who can't use Java 8, or who want an API more focused than {@code CompletableFuture}. (If you
 * need to adapt between {@code CompletableFuture} and {@code ListenableFuture}, consider Future Converter.)
 *
 *
Extension

 *
 * If you want a class like {@code FluentFuture} but with extra methods, we recommend declaring your
 * own subclass of {@link ListenableFuture}, complete with a method like {@link #from} to adapt an
 * existing {@code ListenableFuture}, implemented atop a {@link ForwardingListenableFuture} that
 * forwards to that future and adds the desired methods.
 *
 * @since 23.0
 */
@Beta
@GwtCompatible(emulated = true)
public abstract class FluentFuture<V> extends GwtFluentFutureCatchingSpecialization<V> {

  /**
   * A less abstract subclass of AbstractFuture. This can be used to optimize setFuture by ensuring
   * that {@link #get} calls exactly the implementation of {@link AbstractFuture#get}.
   */
  abstract static class TrustedFuture<V> extends FluentFuture<V>
      implements AbstractFuture.Trusted<V> {
    @CanIgnoreReturnValue
    @Override
    public final V get() throws InterruptedException, ExecutionException {
      return super.get();
    }

    @CanIgnoreReturnValue
    @Override
    public final V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
      return super.get(timeout, unit);
    }

    @Override
    public final boolean isDone() {
      return super.isDone();
    }

    @Override
    public final boolean isCancelled() {
      return super.isCancelled();
    }

    @Override
    public final void addListener(Runnable listener, Executor executor) {
      super.addListener(listener, executor);
    }

    @CanIgnoreReturnValue
    @Override
    public final boolean cancel(boolean mayInterruptIfRunning) {
      return super.cancel(mayInterruptIfRunning);
    }
  }

  FluentFuture() {}

  /**
   * Converts the given {@code ListenableFuture} to an equivalent {@code FluentFuture}.
   *
   *
If the given {@code ListenableFuture} is already a {@code FluentFuture}, it is returned
   * directly. If not, it is wrapped in a {@code FluentFuture} that delegates all calls to the
   * original {@code ListenableFuture}.
   */
  public static <V> FluentFuture<V> from(ListenableFuture<V> future) {
    return future instanceof FluentFuture
        ? (FluentFuture<V>) future
        : new ForwardingFluentFuture<V>(future);
  }

  /**
   * Simply returns its argument.
   *
   * @deprecated no need to use this
   * @since NEXT
   */
  @Deprecated
  public static <V> FluentFuture<V> from(FluentFuture<V> future) {
    return checkNotNull(future);
  }

  /**
   * Returns a {@code Future} whose result is taken from this {@code Future} or, if this {@code
   * Future} fails with the given {@code exceptionType}, from the result provided by the {@code
   * fallback}. {@link Function#apply} is not invoked until the primary input has failed, so if the
   * primary input succeeds, it is never invoked. If, during the invocation of {@code fallback}, an
   * exception is thrown, this exception is used as the result of the output {@code Future}.
   *
   *
Usage example:
   *
   *
{@code
   * // Falling back to a zero counter in case an exception happens when processing the RPC to fetch
   * // counters.
   * ListenableFuture<Integer> faultTolerantFuture =
   *     fetchCounters().catching(FetchException.class, x -> 0, directExecutor());
   * }

   *
   *
When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method.
   *
   *
This method is similar to {@link java.util.concurrent.CompletableFuture#exceptionally}. It
   * can also serve some of the use cases of {@link java.util.concurrent.CompletableFuture#handle}
   * and {@link java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link
   * #transform}.
   *
   * @param exceptionType the exception type that triggers use of {@code fallback}. The exception
   *     type is matched against the input's exception. "The input's exception" means the cause of
   *     the {@link ExecutionException} thrown by {@code input.get()} or, if {@code get()} throws a
   *     different kind of exception, that exception itself. To avoid hiding bugs and other
   *     unrecoverable errors, callers should prefer more specific types, avoiding {@code
   *     Throwable.class} in particular.
   * @param fallback the {@link Function} to be called if the input fails with the expected
   *     exception type. The function's argument is the input's exception. "The input's exception"
   *     means the cause of the {@link ExecutionException} thrown by {@code this.get()} or, if
   *     {@code get()} throws a different kind of exception, that exception itself.
   * @param executor the executor that runs {@code fallback} if the input fails
   */
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public final <X extends Throwable> FluentFuture<V> catching(
      Class<X> exceptionType, Function<? super X, ? extends V> fallback, Executor executor) {
    return (FluentFuture<V>) Futures.catching(this, exceptionType, fallback, executor);
  }

  /**
   * Returns a {@code Future} whose result is taken from this {@code Future} or, if this {@code
   * Future} fails with the given {@code exceptionType}, from the result provided by the {@code
   * fallback}. {@link AsyncFunction#apply} is not invoked until the primary input has failed, so if
   * the primary input succeeds, it is never invoked. If, during the invocation of {@code fallback},
   * an exception is thrown, this exception is used as the result of the output {@code Future}.
   *
   *
Usage examples:
   *
   *
{@code
   * // Falling back to a zero counter in case an exception happens when processing the RPC to fetch
   * // counters.
   * ListenableFuture<Integer> faultTolerantFuture =
   *     fetchCounters().catchingAsync(
   *         FetchException.class, x -> immediateFuture(0), directExecutor());
   * }

   *
   *
The fallback can also choose to propagate the original exception when desired:
   *
   *
{@code
   * // Falling back to a zero counter only in case the exception was a
   * // TimeoutException.
   * ListenableFuture<Integer> faultTolerantFuture =
   *     fetchCounters().catchingAsync(
   *         FetchException.class,
   *         e -> {
   *           if (omitDataOnFetchFailure) {
   *             return immediateFuture(0);
   *           }
   *           throw e;
   *         },
   *         directExecutor());
   * }

   *
   *
When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method. (Specifically,
   * {@code directExecutor} functions should avoid heavyweight operations inside {@code
   * AsyncFunction.apply}. Any heavyweight operations should occur in other threads responsible for
   * completing the returned {@code Future}.)
   *
   *
This method is similar to {@link java.util.concurrent.CompletableFuture#exceptionally}. It
   * can also serve some of the use cases of {@link java.util.concurrent.CompletableFuture#handle}
   * and {@link java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link
   * #transform}.
   *
   * @param exceptionType the exception type that triggers use of {@code fallback}. The exception
   *     type is matched against the input's exception. "The input's exception" means the cause of
   *     the {@link ExecutionException} thrown by {@code this.get()} or, if {@code get()} throws a
   *     different kind of exception, that exception itself. To avoid hiding bugs and other
   *     unrecoverable errors, callers should prefer more specific types, avoiding {@code
   *     Throwable.class} in particular.
   * @param fallback the {@link AsyncFunction} to be called if the input fails with the expected
   *     exception type. The function's argument is the input's exception. "The input's exception"
   *     means the cause of the {@link ExecutionException} thrown by {@code input.get()} or, if
   *     {@code get()} throws a different kind of exception, that exception itself.
   * @param executor the executor that runs {@code fallback} if the input fails
   */
  @Partially.GwtIncompatible("AVAILABLE but requires exceptionType to be Throwable.class")
  public final <X extends Throwable> FluentFuture<V> catchingAsync(
      Class<X> exceptionType, AsyncFunction<? super X, ? extends V> fallback, Executor executor) {
    return (FluentFuture<V>) Futures.catchingAsync(this, exceptionType, fallback, executor);
  }

  /**
   * Returns a future that delegates to this future but will finish early (via a {@link
   * TimeoutException} wrapped in an {@link ExecutionException}) if the specified timeout expires.
   * If the timeout expires, not only will the output future finish, but also the input future
   * ({@code this}) will be cancelled and interrupted.
   *
   * @param timeout when to time out the future
   * @param unit the time unit of the time parameter
   * @param scheduledExecutor The executor service to enforce the timeout.
   */
  @GwtIncompatible // ScheduledExecutorService
  @SuppressWarnings("GoodTime") // should accept a java.time.Duration
  public final FluentFuture<V> withTimeout(
      long timeout, TimeUnit unit, ScheduledExecutorService scheduledExecutor) {
    return (FluentFuture<V>) Futures.withTimeout(this, timeout, unit, scheduledExecutor);
  }

  /**
   * Returns a new {@code Future} whose result is asynchronously derived from the result of this
   * {@code Future}. If the input {@code Future} fails, the returned {@code Future} fails with the
   * same exception (and the function is not invoked).
   *
   *
More precisely, the returned {@code Future} takes its result from a {@code Future} produced
   * by applying the given {@code AsyncFunction} to the result of the original {@code Future}.
   * Example usage:
   *
   *
{@code
   * FluentFuture<RowKey> rowKeyFuture = FluentFuture.from(indexService.lookUp(query));
   * ListenableFuture<QueryResult> queryFuture =
   *     rowKeyFuture.transformAsync(dataService::readFuture, executor);
   * }

   *
   *
When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method. (Specifically,
   * {@code directExecutor} functions should avoid heavyweight operations inside {@code
   * AsyncFunction.apply}. Any heavyweight operations should occur in other threads responsible for
   * completing the returned {@code Future}.)
   *
   *
The returned {@code Future} attempts to keep its cancellation state in sync with that of the
   * input future and that of the future returned by the chain function. That is, if the returned
   * {@code Future} is cancelled, it will attempt to cancel the other two, and if either of the
   * other two is cancelled, the returned {@code Future} will receive a callback in which it will
   * attempt to cancel itself.
   *
   *
This method is similar to {@link java.util.concurrent.CompletableFuture#thenCompose} and
   * {@link java.util.concurrent.CompletableFuture#thenComposeAsync}. It can also serve some of the
   * use cases of {@link java.util.concurrent.CompletableFuture#handle} and {@link
   * java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link #catching}.
   *
   * @param function A function to transform the result of this future to the result of the output
   *     future
   * @param executor Executor to run the function in.
   * @return A future that holds result of the function (if the input succeeded) or the original
   *     input's failure (if not)
   */
  public final <T> FluentFuture<T> transformAsync(
      AsyncFunction<? super V, T> function, Executor executor) {
    return (FluentFuture<T>) Futures.transformAsync(this, function, executor);
  }

  /**
   * Returns a new {@code Future} whose result is derived from the result of this {@code Future}. If
   * this input {@code Future} fails, the returned {@code Future} fails with the same exception (and
   * the function is not invoked). Example usage:
   *
   *
{@code
   * ListenableFuture<List<Row>> rowsFuture =
   *     queryFuture.transform(QueryResult::getRows, executor);
   * }

   *
   *
When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight functions passed to this method.
   *
   *
The returned {@code Future} attempts to keep its cancellation state in sync with that of the
   * input future. That is, if the returned {@code Future} is cancelled, it will attempt to cancel
   * the input, and if the input is cancelled, the returned {@code Future} will receive a callback
   * in which it will attempt to cancel itself.
   *
   *
An example use of this method is to convert a serializable object returned from an RPC into
   * a POJO.
   *
   *
This method is similar to {@link java.util.concurrent.CompletableFuture#thenApply} and
   * {@link java.util.concurrent.CompletableFuture#thenApplyAsync}. It can also serve some of the
   * use cases of {@link java.util.concurrent.CompletableFuture#handle} and {@link
   * java.util.concurrent.CompletableFuture#handleAsync} when used along with {@link #catching}.
   *
   * @param function A Function to transform the results of this future to the results of the
   *     returned future.
   * @param executor Executor to run the function in.
   * @return A future that holds result of the transformation.
   */
  public final <T> FluentFuture<T> transform(Function<? super V, T> function, Executor executor) {
    return (FluentFuture<T>) Futures.transform(this, function, executor);
  }

  /**
   * Registers separate success and failure callbacks to be run when this {@code Future}'s
   * computation is {@linkplain java.util.concurrent.Future#isDone() complete} or, if the
   * computation is already complete, immediately.
   *
   *
The callback is run on {@code executor}. There is no guaranteed ordering of execution of
   * callbacks, but any callback added through this method is guaranteed to be called once the
   * computation is complete.
   *
   *
Example:
   *
   *
{@code
   * future.addCallback(
   *     new FutureCallback<QueryResult>() {
   *       public void onSuccess(QueryResult result) {
   *         storeInCache(result);
   *       }
   *       public void onFailure(Throwable t) {
   *         reportError(t);
   *       }
   *     }, executor);
   * }

   *
   *
When selecting an executor, note that {@code directExecutor} is dangerous in some cases. See
   * the discussion in the {@link #addListener} documentation. All its warnings about heavyweight
   * listeners are also applicable to heavyweight callbacks passed to this method.
   *
   *
For a more general interface to attach a completion listener, see {@link #addListener}.
   *
   *
This method is similar to {@link java.util.concurrent.CompletableFuture#whenComplete} and
   * {@link java.util.concurrent.CompletableFuture#whenCompleteAsync}. It also serves the use case
   * of {@link java.util.concurrent.CompletableFuture#thenAccept} and {@link
   * java.util.concurrent.CompletableFuture#thenAcceptAsync}.
   *
   * @param callback The callback to invoke when this {@code Future} is completed.
   * @param executor The executor to run {@code callback} when the future completes.
   */
  public final void addCallback(FutureCallback<? super V> callback, Executor executor) {
    Futures.addCallback(this, callback, executor);
  }
}


/*
 * Copyright (C) 2014 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.graph;

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

import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.graph.GraphConstants.Presence;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.Immutable;

/**
 * A {@link Graph} whose elements and structural relationships will never change. Instances of this
 * class may be obtained with {@link #copyOf(Graph)}.
 *
 *
See the Guava User's Guide's discussion
 * of the {@code Immutable*} types for more information on the properties and guarantees
 * provided by this class.
 *
 * @author James Sexton
 * @author Joshua O'Madadhain
 * @author Omar Darwish
 * @author Jens Nyman
 * @param <N> Node parameter type
 * @since 20.0
 */
@Beta
@Immutable(containerOf = {"N"})
public class ImmutableGraph<N> extends ForwardingGraph<N> {
  @SuppressWarnings("Immutable") // The backing graph must be immutable.
  private final BaseGraph<N> backingGraph;

  ImmutableGraph(BaseGraph<N> backingGraph) {
    this.backingGraph = backingGraph;
  }

  /** Returns an immutable copy of {@code graph}. */
  public static <N> ImmutableGraph<N> copyOf(Graph<N> graph) {
    return (graph instanceof ImmutableGraph)
        ? (ImmutableGraph<N>) graph
        : new ImmutableGraph<N>(
            new ConfigurableValueGraph<N, Presence>(
                GraphBuilder.from(graph), getNodeConnections(graph), graph.edges().size()));
  }

  /**
   * Simply returns its argument.
   *
   * @deprecated no need to use this
   */
  @Deprecated
  public static <N> ImmutableGraph<N> copyOf(ImmutableGraph<N> graph) {
    return checkNotNull(graph);
  }

  private static <N> ImmutableMap<N, GraphConnections<N, Presence>> getNodeConnections(
      Graph<N> graph) {
    // ImmutableMap.Builder maintains the order of the elements as inserted, so the map will have
    // whatever ordering the graph's nodes do, so ImmutableSortedMap is unnecessary even if the
    // input nodes are sorted.
    ImmutableMap.Builder<N, GraphConnections<N, Presence>> nodeConnections = ImmutableMap.builder();
    for (N node : graph.nodes()) {
      nodeConnections.put(node, connectionsOf(graph, node));
    }
    return nodeConnections.build();
  }

  private static <N> GraphConnections<N, Presence> connectionsOf(Graph<N> graph, N node) {
    Function<Object, Presence> edgeValueFn = Functions.constant(Presence.EDGE_EXISTS);
    return graph.isDirected()
        ? DirectedGraphConnections.ofImmutable(
            graph.predecessors(node), Maps.asMap(graph.successors(node), edgeValueFn))
        : UndirectedGraphConnections.ofImmutable(
            Maps.asMap(graph.adjacentNodes(node), edgeValueFn));
  }

  @Override
  protected BaseGraph<N> delegate() {
    return backingGraph;
  }

  /**
   * A builder for creating {@link ImmutableGraph} instances, especially {@code static final}
   * graphs. Example:
   *
   *
{@code
   * static final ImmutableGraph<Country> COUNTRY_ADJACENCY_GRAPH =
   *     GraphBuilder.undirected()
   *         .<Country>immutable()
   *         .putEdge(FRANCE, GERMANY)
   *         .putEdge(FRANCE, BELGIUM)
   *         .putEdge(GERMANY, BELGIUM)
   *         .addNode(ICELAND)
   *         .build();
   * }

   *
   *
Builder instances can be reused; it is safe to call {@link #build} multiple times to build
   * multiple graphs in series. Each new graph contains all the elements of the ones created before
   * it.
   *
   * @since NEXT
   */
  public static class Builder<N> {

    private final MutableGraph<N> mutableGraph;

    Builder(GraphBuilder<N> graphBuilder) {
      this.mutableGraph = graphBuilder.build();
    }

    /**
     * Adds {@code node} if it is not already present.
     *
     *
Nodes must be unique, just as {@code Map} keys must be. They must also be non-null.
     *
     * @return this {@code Builder} object
     */
    @CanIgnoreReturnValue
    public Builder<N> addNode(N node) {
      mutableGraph.addNode(node);
      return this;
    }

    /**
     * Adds an edge connecting {@code nodeU} to {@code nodeV} if one is not already present.
     *
     *
If the graph is directed, the resultant edge will be directed; otherwise, it will be
     * undirected.
     *
     *
If {@code nodeU} and {@code nodeV} are not already present in this graph, this method will
     * silently {@link #addNode(Object) add} {@code nodeU} and {@code nodeV} to the graph.
     *
     * @return this {@code Builder} object
     * @throws IllegalArgumentException if the introduction of the edge would violate {@link
     *     #allowsSelfLoops()}
     */
    @CanIgnoreReturnValue
    public Builder<N> putEdge(N nodeU, N nodeV) {
      mutableGraph.putEdge(nodeU, nodeV);
      return this;
    }

    /**
     * Adds an edge connecting {@code endpoints} (in the order, if any, specified by {@code
     * endpoints}) if one is not already present.
     *
     *
If this graph is directed, {@code endpoints} must be ordered and the added edge will be
     * directed; if it is undirected, the added edge will be undirected.
     *
     *
If this graph is directed, {@code endpoints} must be ordered.
     *
     *
If either or both endpoints are not already present in this graph, this method will
     * silently {@link #addNode(Object) add} each missing endpoint to the graph.
     *
     * @return this {@code Builder} object
     * @throws IllegalArgumentException if the introduction of the edge would violate {@link
     *     #allowsSelfLoops()}
     * @throws IllegalArgumentException if the endpoints are unordered and the graph is directed
     */
    @CanIgnoreReturnValue
    public Builder<N> putEdge(EndpointPair<N> endpoints) {
      mutableGraph.putEdge(endpoints);
      return this;
    }

    /**
     * Returns a newly-created {@code ImmutableGraph} based on the contents of this {@code Builder}.
     */
    public ImmutableGraph<N> build() {
      return ImmutableGraph.copyOf(mutableGraph);
    }
  }
}


/*
 * 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 static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.math.IntMath;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.concurrent.LazyInit;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

/**
 * A {@link SortedMultiset} whose contents will never change, with many other important properties
 * detailed at {@link ImmutableCollection}.
 *
 *
Warning: as with any sorted collection, you are strongly advised not to use a {@link
 * Comparator} or {@link Comparable} type whose comparison behavior is inconsistent with
 * equals. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
 * if and only if {@code a.equals(b)}. If this advice is not followed, the resulting
 * collection will not correctly obey its specification.
 *
 *
See the Guava User Guide article on  immutable collections.
 *
 * @author Louis Wasserman
 * @since 12.0
 */
@GwtIncompatible // hasn't been tested yet
public abstract class ImmutableSortedMultiset<E> extends ImmutableSortedMultisetFauxverideShim<E>
    implements SortedMultiset<E> {
  // TODO(lowasser): GWT compatibility

  /** Returns the empty immutable sorted multiset. */
  @SuppressWarnings("unchecked")
  public static <E> ImmutableSortedMultiset<E> of() {
    return (ImmutableSortedMultiset) RegularImmutableSortedMultiset.NATURAL_EMPTY_MULTISET;
  }

  /** Returns an immutable sorted multiset containing a single element. */
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E element) {
    RegularImmutableSortedSet<E> elementSet =
        (RegularImmutableSortedSet<E>) ImmutableSortedSet.of(element);
    long[] cumulativeCounts = {0, 1};
    return new RegularImmutableSortedMultiset<E>(elementSet, cumulativeCounts, 0, 1);
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   * @throws NullPointerException if any element is null
   */
  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E e1, E e2) {
    return copyOf(Ordering.natural(), Arrays.asList(e1, e2));
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   * @throws NullPointerException if any element is null
   */
  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E e1, E e2, E e3) {
    return copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3));
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   * @throws NullPointerException if any element is null
   */
  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(
      E e1, E e2, E e3, E e4) {
    return copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3, e4));
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   * @throws NullPointerException if any element is null
   */
  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(
      E e1, E e2, E e3, E e4, E e5) {
    return copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3, e4, e5));
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   * @throws NullPointerException if any element is null
   */
  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(
      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
    int size = remaining.length + 6;
    List<E> all = Lists.newArrayListWithCapacity(size);
    Collections.addAll(all, e1, e2, e3, e4, e5, e6);
    Collections.addAll(all, remaining);
    return copyOf(Ordering.natural(), all);
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   * @throws NullPointerException if any of {@code elements} is null
   */
  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> copyOf(E[] elements) {
    return copyOf(Ordering.natural(), Arrays.asList(elements));
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering. To create a copy of a {@code SortedMultiset} that preserves the comparator, call
   * {@link #copyOfSorted} instead. This method iterates over {@code elements} at most once.
   *
   *
Note that if {@code s} is a {@code Multiset<String>}, then {@code
   * ImmutableSortedMultiset.copyOf(s)} returns an {@code ImmutableSortedMultiset<String>}
   * containing each of the strings in {@code s}, while {@code ImmutableSortedMultiset.of(s)}
   * returns an {@code ImmutableSortedMultiset<Multiset<String>>} containing one element (the given
   * multiset itself).
   *
   *
Despite the method name, this method attempts to avoid actually copying the data when it is
   * safe to do so. The exact circumstances under which a copy will or will not be performed are
   * undocumented and subject to change.
   *
   *
This method is not type-safe, as it may be called on elements that are not mutually
   * comparable.
   *
   * @throws ClassCastException if the elements are not mutually comparable
   * @throws NullPointerException if any of {@code elements} is null
   */
  public static <E> ImmutableSortedMultiset<E> copyOf(Iterable<? extends E> elements) {
    // Hack around E not being a subtype of Comparable.
    // Unsafe, see ImmutableSortedMultisetFauxverideShim.
    @SuppressWarnings("unchecked")
    Ordering<E> naturalOrder = (Ordering<E>) Ordering.<Comparable>natural();
    return copyOf(naturalOrder, elements);
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by their natural
   * ordering.
   *
   *
This method is not type-safe, as it may be called on elements that are not mutually
   * comparable.
   *
   * @throws ClassCastException if the elements are not mutually comparable
   * @throws NullPointerException if any of {@code elements} is null
   */
  public static <E> ImmutableSortedMultiset<E> copyOf(Iterator<? extends E> elements) {
    // Hack around E not being a subtype of Comparable.
    // Unsafe, see ImmutableSortedMultisetFauxverideShim.
    @SuppressWarnings("unchecked")
    Ordering<E> naturalOrder = (Ordering<E>) Ordering.<Comparable>natural();
    return copyOf(naturalOrder, elements);
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by the given {@code
   * Comparator}.
   *
   * @throws NullPointerException if {@code comparator} or any of {@code elements} is null
   */
  public static <E> ImmutableSortedMultiset<E> copyOf(
      Comparator<? super E> comparator, Iterator<? extends E> elements) {
    checkNotNull(comparator);
    return new Builder<E>(comparator).addAll(elements).build();
  }

  /**
   * Returns an immutable sorted multiset containing the given elements sorted by the given {@code
   * Comparator}. This method iterates over {@code elements} at most once.
   *
   *
Despite the method name, this method attempts to avoid actually copying the data when it is
   * safe to do so. The exact circumstances under which a copy will or will not be performed are
   * undocumented and subject to change.
   *
   * @throws NullPointerException if {@code comparator} or any of {@code elements} is null
   */
  @SuppressWarnings("unchecked")
  public static <E> ImmutableSortedMultiset<E> copyOf(
      Comparator<? super E> comparator, Iterable<? extends E> elements) {
    if (elements instanceof ImmutableSortedMultiset) {
      @SuppressWarnings("unchecked") // immutable collections are always safe for covariant casts
      ImmutableSortedMultiset<E> multiset = (ImmutableSortedMultiset<E>) elements;
      if (comparator.equals(multiset.comparator())) {
        if (multiset.isPartialView()) {
          return copyOfSortedEntries(comparator, multiset.entrySet().asList());
        } else {
          return multiset;
        }
      }
    }
    return new ImmutableSortedMultiset.Builder<E>(comparator).addAll(elements).build();
  }

  /**
   * Returns an immutable sorted multiset containing the elements of a sorted multiset, sorted by
   * the same {@code Comparator}. That behavior differs from {@link #copyOf(Iterable)}, which always
   * uses the natural ordering of the elements.
   *
   *
Despite the method name, this method attempts to avoid actually copying the data when it is
   * safe to do so. The exact circumstances under which a copy will or will not be performed are
   * undocumented and subject to change.
   *
   *
This method is safe to use even when {@code sortedMultiset} is a synchronized or concurrent
   * collection that is currently being modified by another thread.
   *
   * @throws NullPointerException if {@code sortedMultiset} or any of its elements is null
   */
  public static <E> ImmutableSortedMultiset<E> copyOfSorted(SortedMultiset<E> sortedMultiset) {
    return copyOfSortedEntries(
        sortedMultiset.comparator(), Lists.newArrayList(sortedMultiset.entrySet()));
  }

  private static <E> ImmutableSortedMultiset<E> copyOfSortedEntries(
      Comparator<? super E> comparator, Collection<Entry<E>> entries) {
    if (entries.isEmpty()) {
      return emptyMultiset(comparator);
    }
    ImmutableList.Builder<E> elementsBuilder = new ImmutableList.Builder<E>(entries.size());
    long[] cumulativeCounts = new long[entries.size() + 1];
    int i = 0;
    for (Entry<E> entry : entries) {
      elementsBuilder.add(entry.getElement());
      cumulativeCounts[i + 1] = cumulativeCounts[i] + entry.getCount();
      i++;
    }
    return new RegularImmutableSortedMultiset<E>(
        new RegularImmutableSortedSet<E>(elementsBuilder.build(), comparator),
        cumulativeCounts,
        0,
        entries.size());
  }

  @SuppressWarnings("unchecked")
  static <E> ImmutableSortedMultiset<E> emptyMultiset(Comparator<? super E> comparator) {
    if (Ordering.natural().equals(comparator)) {
      return (ImmutableSortedMultiset<E>) RegularImmutableSortedMultiset.NATURAL_EMPTY_MULTISET;
    } else {
      return new RegularImmutableSortedMultiset<E>(comparator);
    }
  }

  ImmutableSortedMultiset() {}

  @Override
  public final Comparator<? super E> comparator() {
    return elementSet().comparator();
  }

  @Override
  public abstract ImmutableSortedSet<E> elementSet();

  @LazyInit transient ImmutableSortedMultiset<E> descendingMultiset;

  @Override
  public ImmutableSortedMultiset<E> descendingMultiset() {
    ImmutableSortedMultiset<E> result = descendingMultiset;
    if (result == null) {
      return descendingMultiset =
          this.isEmpty()
              ? emptyMultiset(Ordering.from(comparator()).reverse())
              : new DescendingImmutableSortedMultiset<E>(this);
    }
    return result;
  }

  /**
   * {@inheritDoc}
   *
   *
This implementation is guaranteed to throw an {@link UnsupportedOperationException}.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public final Entry<E> pollFirstEntry() {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   *
   *
This implementation is guaranteed to throw an {@link UnsupportedOperationException}.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public final Entry<E> pollLastEntry() {
    throw new UnsupportedOperationException();
  }

  @Override
  public abstract ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType);

  @Override
  public ImmutableSortedMultiset<E> subMultiset(
      E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
    checkArgument(
        comparator().compare(lowerBound, upperBound) <= 0,
        "Expected lowerBound <= upperBound but %s > %s",
        lowerBound,
        upperBound);
    return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType);
  }

  @Override
  public abstract ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType);

  /**
   * Returns a builder that creates immutable sorted multisets with an explicit comparator. If the
   * comparator has a more general type than the set being generated, such as creating a {@code
   * SortedMultiset<Integer>} with a {@code Comparator<Number>}, use the {@link Builder} constructor
   * instead.
   *
   * @throws NullPointerException if {@code comparator} is null
   */
  public static <E> Builder<E> orderedBy(Comparator<E> comparator) {
    return new Builder<E>(comparator);
  }

  /**
   * Returns a builder that creates immutable sorted multisets whose elements are ordered by the
   * reverse of their natural ordering.
   *
   *
Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
   * Comparable<? super E>} as a workaround for javac bug 6468354.
   */
  public static <E extends Comparable<?>> Builder<E> reverseOrder() {
    return new Builder<E>(Ordering.natural().reverse());
  }

  /**
   * Returns a builder that creates immutable sorted multisets whose elements are ordered by their
   * natural ordering. The sorted multisets use {@link Ordering#natural()} as the comparator. This
   * method provides more type-safety than {@link #builder}, as it can be called only for classes
   * that implement {@link Comparable}.
   *
   *
Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
   * Comparable<? super E>} as a workaround for javac bug 6468354.
   */
  public static <E extends Comparable<?>> Builder<E> naturalOrder() {
    return new Builder<E>(Ordering.natural());
  }

  /**
   * A builder for creating immutable multiset instances, especially {@code public static final}
   * multisets ("constant multisets"). Example:
   *
   *
{@code
   * public static final ImmutableSortedMultiset<Bean> BEANS =
   *     new ImmutableSortedMultiset.Builder<Bean>(colorComparator())
   *         .addCopies(Bean.COCOA, 4)
   *         .addCopies(Bean.GARDEN, 6)
   *         .addCopies(Bean.RED, 8)
   *         .addCopies(Bean.BLACK_EYED, 10)
   *         .build();
   * }

   *
   *
Builder instances can be reused; it is safe to call {@link #build} multiple times to build
   * multiple multisets in series.
   *
   * @since 12.0
   */
  public static class Builder<E> extends ImmutableMultiset.Builder<E> {
    /*
     * We keep an array of elements and counts.  Periodically -- when we need more room in the
     * array, or when we're building, or the like -- we sort, deduplicate, and combine the counts.
     * Negative counts indicate a setCount operation with ~counts[i].
     */

    private final Comparator<? super E> comparator;

    @VisibleForTesting E[] elements;
    private int[] counts;

    /*
     * The number of used positions in the elements array.  We deduplicate periodically, so this
     * may fluctuate up and down.
     */
    private int length;

    // True if we just called build() and the elements array is being used by a created ISM, meaning
    // we shouldn't modify that array further.
    private boolean forceCopyElements;

    /**
     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
     * ImmutableSortedMultiset#orderedBy(Comparator)}.
     */
    @SuppressWarnings("unchecked")
    public Builder(Comparator<? super E> comparator) {
      super(true); // doesn't allocate hash table in supertype
      this.comparator = checkNotNull(comparator);
      this.elements = (E[]) new Object[ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY];
      this.counts = new int[ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY];
    }

    /** Check if we need to do deduplication and coalescing, and if so, do it. */
    private void maintenance() {
      if (length == elements.length) {
        dedupAndCoalesce(true);
      } else if (forceCopyElements) {
        this.elements = Arrays.copyOf(elements, elements.length);
        // we don't currently need to copy the counts array, because we don't use it directly
        // in built ISMs
      }
      forceCopyElements = false;
    }

    private void dedupAndCoalesce(boolean maybeExpand) {
      if (length == 0) {
        return;
      }
      E[] sortedElements = Arrays.copyOf(elements, length);
      Arrays.sort(sortedElements, comparator);
      int uniques = 1;
      for (int i = 1; i < sortedElements.length; i++) {
        if (comparator.compare(sortedElements[uniques - 1], sortedElements[i]) < 0) {
          sortedElements[uniques] = sortedElements[i];
          uniques++;
        }
      }
      Arrays.fill(sortedElements, uniques, length, null);
      if (maybeExpand && uniques * 4 > length * 3) {
        // lots of nonduplicated elements, expand the array by 50%
        sortedElements =
            Arrays.copyOf(sortedElements, IntMath.saturatedAdd(length, length / 2 + 1));
      }
      int[] sortedCounts = new int[sortedElements.length];
      for (int i = 0; i < length; i++) {
        int index = Arrays.binarySearch(sortedElements, 0, uniques, elements[i], comparator);
        if (counts[i] >= 0) {
          sortedCounts[index] += counts[i];
        } else {
          sortedCounts[index] = ~counts[i];
        }
      }
      // Note that we're not getting rid, yet, of elements with count 0.  We'll do that in build().
      this.elements = sortedElements;
      this.counts = sortedCounts;
      this.length = uniques;
    }

    /**
     * Adds {@code element} to the {@code ImmutableSortedMultiset}.
     *
     * @param element the element to add
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code element} is null
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> add(E element) {
      return addCopies(element, 1);
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableSortedMultiset}.
     *
     * @param elements the elements to add
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code elements} is null or contains a null element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> add(E... elements) {
      for (E element : elements) {
        add(element);
      }
      return this;
    }

    /**
     * Adds a number of occurrences of an element to this {@code ImmutableSortedMultiset}.
     *
     * @param element the element to add
     * @param occurrences the number of occurrences of the element to add. May be zero, in which
     *     case no change will be made.
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code element} is null
     * @throws IllegalArgumentException if {@code occurrences} is negative, or if this operation
     *     would result in more than {@link Integer#MAX_VALUE} occurrences of the element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> addCopies(E element, int occurrences) {
      checkNotNull(element);
      CollectPreconditions.checkNonnegative(occurrences, "occurrences");
      if (occurrences == 0) {
        return this;
      }
      maintenance();
      elements[length] = element;
      counts[length] = occurrences;
      length++;
      return this;
    }

    /**
     * Adds or removes the necessary occurrences of an element such that the element attains the
     * desired count.
     *
     * @param element the element to add or remove occurrences of
     * @param count the desired count of the element in this multiset
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code element} is null
     * @throws IllegalArgumentException if {@code count} is negative
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> setCount(E element, int count) {
      checkNotNull(element);
      CollectPreconditions.checkNonnegative(count, "count");
      maintenance();
      elements[length] = element;
      counts[length] = ~count;
      length++;
      return this;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableSortedMultiset}.
     *
     * @param elements the {@code Iterable} to add to the {@code ImmutableSortedMultiset}
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code elements} is null or contains a null element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> addAll(Iterable<? extends E> elements) {
      if (elements instanceof Multiset) {
        for (Entry<? extends E> entry : ((Multiset<? extends E>) elements).entrySet()) {
          addCopies(entry.getElement(), entry.getCount());
        }
      } else {
        for (E e : elements) {
          add(e);
        }
      }
      return this;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableSortedMultiset}.
     *
     * @param elements the elements to add to the {@code ImmutableSortedMultiset}
     * @return this {@code Builder} object
     * @throws NullPointerException if {@code elements} is null or contains a null element
     */
    @CanIgnoreReturnValue
    @Override
    public Builder<E> addAll(Iterator<? extends E> elements) {
      while (elements.hasNext()) {
        add(elements.next());
      }
      return this;
    }

    private void dedupAndCoalesceAndDeleteEmpty() {
      dedupAndCoalesce(false);

      // If there was a setCount(elem, 0), those elements are still present.  Eliminate them.
      int size = 0;
      for (int i = 0; i < length; i++) {
        if (counts[i] > 0) {
          elements[size] = elements[i];
          counts[size] = counts[i];
          size++;
        }
      }
      Arrays.fill(elements, size, length, null);
      Arrays.fill(counts, size, length, 0);
      length = size;
    }

    /**
     * Returns a newly-created {@code ImmutableSortedMultiset} based on the contents of the {@code
     * Builder}.
     */
    @Override
    public ImmutableSortedMultiset<E> build() {
      dedupAndCoalesceAndDeleteEmpty();
      if (length == 0) {
        return emptyMultiset(comparator);
      }
      RegularImmutableSortedSet<E> elementSet =
          (RegularImmutableSortedSet<E>) ImmutableSortedSet.construct(comparator, length, elements);
      long[] cumulativeCounts = new long[length + 1];
      for (int i = 0; i < length; i++) {
        cumulativeCounts[i + 1] = cumulativeCounts[i] + counts[i];
      }
      forceCopyElements = true;
      return new RegularImmutableSortedMultiset<E>(elementSet, cumulativeCounts, 0, length);
    }
  }

  private static final class SerializedForm<E> implements Serializable {
    final Comparator<? super E> comparator;
    final E[] elements;
    final int[] counts;

    @SuppressWarnings("unchecked")
    SerializedForm(SortedMultiset<E> multiset) {
      this.comparator = multiset.comparator();
      int n = multiset.entrySet().size();
      elements = (E[]) new Object[n];
      counts = new int[n];
      int i = 0;
      for (Entry<E> entry : multiset.entrySet()) {
        elements[i] = entry.getElement();
        counts[i] = entry.getCount();
        i++;
      }
    }

    Object readResolve() {
      int n = elements.length;
      Builder<E> builder = new Builder<>(comparator);
      for (int i = 0; i < n; i++) {
        builder.addCopies(elements[i], counts[i]);
      }
      return builder.build();
    }
  }

  @Override
  Object writeReplace() {
    return new SerializedForm<E>(this);
  }
}


/*
 * 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 com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Iterator;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A collection which forwards all its method calls to another collection. Subclasses should
 * override one or more methods to modify the behavior of the backing collection as desired per the
 * decorator pattern.
 *
 *
Warning: The methods of {@code ForwardingCollection} forward indiscriminately to
 * the methods of the delegate. For example, overriding {@link #add} alone will not change
 * the behavior of {@link #addAll}, which can lead to unexpected behavior. In this case, you should
 * override {@code addAll} as well, either providing your own implementation, or delegating to the
 * provided {@code standardAddAll} method.
 *
 *
{@code default} method warning: This class does not forward calls to {@code
 * default} methods. Instead, it inherits their default implementations. When those implementations
 * invoke methods, they invoke methods on the {@code ForwardingCollection}.
 *
 *
The {@code standard} methods are not guaranteed to be thread-safe, even when all of the
 * methods that they depend on are thread-safe.
 *
 * @author Kevin Bourrillion
 * @author Louis Wasserman
 * @since 2.0
 */
@GwtCompatible
public abstract class ForwardingCollection<E> extends ForwardingObject implements Collection<E> {
  // TODO(lowasser): identify places where thread safety is actually lost

  /** Constructor for use by subclasses. */
  protected ForwardingCollection() {}

  @Override
  protected abstract Collection<E> delegate();

  @Override
  public Iterator<E> iterator() {
    return delegate().iterator();
  }

  @Override
  public int size() {
    return delegate().size();
  }

  @CanIgnoreReturnValue
  @Override
  public boolean removeAll(Collection<?> collection) {
    return delegate().removeAll(collection);
  }

  @Override
  public boolean isEmpty() {
    return delegate().isEmpty();
  }

  @Override
  public boolean contains(Object object) {
    return delegate().contains(object);
  }

  @CanIgnoreReturnValue
  @Override
  public boolean add(E element) {
    return delegate().add(element);
  }

  @CanIgnoreReturnValue
  @Override
  public boolean remove(Object object) {
    return delegate().remove(object);
  }

  @Override
  public boolean containsAll(Collection<?> collection) {
    return delegate().containsAll(collection);
  }

  @CanIgnoreReturnValue
  @Override
  public boolean addAll(Collection<? extends E> collection) {
    return delegate().addAll(collection);
  }

  @CanIgnoreReturnValue
  @Override
  public boolean retainAll(Collection<?> collection) {
    return delegate().retainAll(collection);
  }

  @Override
  public void clear() {
    delegate().clear();
  }

  @Override
  public Object[] toArray() {
    return delegate().toArray();
  }

  @CanIgnoreReturnValue
  @Override
  public <T> T[] toArray(T[] array) {
    return delegate().toArray(array);
  }

  /**
   * A sensible definition of {@link #contains} in terms of {@link #iterator}. If you override
   * {@link #iterator}, you may wish to override {@link #contains} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  protected boolean standardContains(@Nullable Object object) {
    return Iterators.contains(iterator(), object);
  }

  /**
   * A sensible definition of {@link #containsAll} in terms of {@link #contains} . If you override
   * {@link #contains}, you may wish to override {@link #containsAll} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  protected boolean standardContainsAll(Collection<?> collection) {
    return Collections2.containsAllImpl(this, collection);
  }

  /**
   * A sensible definition of {@link #addAll} in terms of {@link #add}. If you override {@link
   * #add}, you may wish to override {@link #addAll} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardAddAll(Collection<? extends E> collection) {
    return Iterators.addAll(this, collection.iterator());
  }

  /**
   * A sensible definition of {@link #remove} in terms of {@link #iterator}, using the iterator's
   * {@code remove} method. If you override {@link #iterator}, you may wish to override {@link
   * #remove} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardRemove(@Nullable Object object) {
    Iterator<E> iterator = iterator();
    while (iterator.hasNext()) {
      if (Objects.equal(iterator.next(), object)) {
        iterator.remove();
        return true;
      }
    }
    return false;
  }

  /**
   * A sensible definition of {@link #removeAll} in terms of {@link #iterator}, using the iterator's
   * {@code remove} method. If you override {@link #iterator}, you may wish to override {@link
   * #removeAll} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardRemoveAll(Collection<?> collection) {
    return Iterators.removeAll(iterator(), collection);
  }

  /**
   * A sensible definition of {@link #retainAll} in terms of {@link #iterator}, using the iterator's
   * {@code remove} method. If you override {@link #iterator}, you may wish to override {@link
   * #retainAll} to forward to this implementation.
   *
   * @since 7.0
   */
  protected boolean standardRetainAll(Collection<?> collection) {
    return Iterators.retainAll(iterator(), collection);
  }

  /**
   * A sensible definition of {@link #clear} in terms of {@link #iterator}, using the iterator's
   * {@code remove} method. If you override {@link #iterator}, you may wish to override {@link
   * #clear} to forward to this implementation.
   *
   * @since 7.0
   */
  protected void standardClear() {
    Iterators.clear(iterator());
  }

  /**
   * A sensible definition of {@link #isEmpty} as {@code !iterator().hasNext}. If you override
   * {@link #isEmpty}, you may wish to override {@link #isEmpty} to forward to this implementation.
   * Alternately, it may be more efficient to implement {@code isEmpty} as {@code size() == 0}.
   *
   * @since 7.0
   */
  protected boolean standardIsEmpty() {
    return !iterator().hasNext();
  }

  /**
   * A sensible definition of {@link #toString} in terms of {@link #iterator}. If you override
   * {@link #iterator}, you may wish to override {@link #toString} to forward to this
   * implementation.
   *
   * @since 7.0
   */
  protected String standardToString() {
    return Collections2.toStringImpl(this);
  }

  /**
   * A sensible definition of {@link #toArray()} in terms of {@link #toArray(Object[])}. If you
   * override {@link #toArray(Object[])}, you may wish to override {@link #toArray} to forward to
   * this implementation.
   *
   * @since 7.0
   */
  protected Object[] standardToArray() {
    Object[] newArray = new Object[size()];
    return toArray(newArray);
  }

  /**
   * A sensible definition of {@link #toArray(Object[])} in terms of {@link #size} and {@link
   * #iterator}. If you override either of these methods, you may wish to override {@link #toArray}
   * to forward to this implementation.
   *
   * @since 7.0
   */
  protected <T> T[] standardToArray(T[] array) {
    return ObjectArrays.toArrayImpl(this, array);
  }
}