/*
 * 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.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;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.stream.Collector;

/**
 * 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 a {@code Collector} that accumulates the input elements into a new {@code
   * ImmutableMultiset}. Elements are sorted by the specified comparator.
   *
   *
Warning: {@code comparator} should be consistent with {@code equals} as
   * explained in the {@link Comparator} documentation.
   *
   * @since 21.0
   */
  public static <E> Collector<E, ?, ImmutableSortedMultiset<E>> toImmutableSortedMultiset(
      Comparator<? super E> comparator) {
    return toImmutableSortedMultiset(comparator, Function.identity(), e -> 1);
  }

  /**
   * Returns a {@code Collector} that accumulates elements into an {@code ImmutableSortedMultiset}
   * whose elements are the result of applying {@code elementFunction} to the inputs, with counts
   * equal to the result of applying {@code countFunction} to the inputs.
   *
   *
If the mapped elements contain duplicates (according to {@code comparator}), the first
   * occurrence in encounter order appears in the resulting multiset, with count equal to the sum of
   * the outputs of {@code countFunction.applyAsInt(t)} for each {@code t} mapped to that element.
   *
   * @since 22.0
   */
  public static <T, E> Collector<T, ?, ImmutableSortedMultiset<E>> toImmutableSortedMultiset(
      Comparator<? super E> comparator,
      Function<? super T, ? extends E> elementFunction,
      ToIntFunction<? super T> countFunction) {
    checkNotNull(comparator);
    checkNotNull(elementFunction);
    checkNotNull(countFunction);
    return Collector.of(
        () -> TreeMultiset.create(comparator),
        (multiset, t) ->
            multiset.add(checkNotNull(elementFunction.apply(t)), countFunction.applyAsInt(t)),
        (multiset1, multiset2) -> {
          multiset1.addAll(multiset2);
          return multiset1;
        },
        (Multiset<E> multiset) -> copyOfSortedEntries(comparator, multiset.entrySet()));
  }

  /** 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
   */
  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;
        }
      }
    }
    elements = Lists.newArrayList(elements); // defensive copy
    TreeMultiset<E> sortedCopy = TreeMultiset.create(checkNotNull(comparator));
    Iterables.addAll(sortedCopy, elements);
    return copyOfSortedEntries(comparator, sortedCopy.entrySet());
  }

  /**
   * 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> {
    /**
     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
     * ImmutableSortedMultiset#orderedBy(Comparator)}.
     */
    public Builder(Comparator<? super E> comparator) {
      super(TreeMultiset.<E>create(checkNotNull(comparator)));
    }

    /**
     * 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) {
      super.add(element);
      return this;
    }

    /**
     * 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) {
      super.add(elements);
      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) {
      super.addCopies(element, occurrences);
      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) {
      super.setCount(element, count);
      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) {
      super.addAll(elements);
      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) {
      super.addAll(elements);
      return this;
    }

    /**
     * Returns a newly-created {@code ImmutableSortedMultiset} based on the contents of the {@code
     * Builder}.
     */
    @Override
    public ImmutableSortedMultiset<E> build() {
      return copyOfSorted((SortedMultiset<E>) contents);
    }
  }

  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) 2013 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.reflect;

import com.google.common.collect.Sets;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Set;

/**
 * Based on what a {@link Type} is, dispatch it to the corresponding {@code visit*} method. By
 * default, no recursion is done for type arguments or type bounds. But subclasses can opt to do
 * recursion by calling {@link #visit} for any {@code Type} while visitation is in progress. For
 * example, this can be used to reject wildcards or type variables contained in a type as in:
 *
 *
{@code
 * new TypeVisitor() {
 *   protected void visitParameterizedType(ParameterizedType t) {
 *     visit(t.getOwnerType());
 *     visit(t.getActualTypeArguments());
 *   }
 *   protected void visitGenericArrayType(GenericArrayType t) {
 *     visit(t.getGenericComponentType());
 *   }
 *   protected void visitTypeVariable(TypeVariable<?> t) {
 *     throw new IllegalArgumentException("Cannot contain type variable.");
 *   }
 *   protected void visitWildcardType(WildcardType t) {
 *     throw new IllegalArgumentException("Cannot contain wildcard type.");
 *   }
 * }.visit(type);
 * }

 *
 *
One {@code Type} is visited at most once. The second time the same type is visited, it's
 * ignored by {@link #visit}. This avoids infinite recursion caused by recursive type bounds.
 *
 *
This class is not thread safe.
 *
 * @author Ben Yu
 */
abstract class TypeVisitor {

  private final Set<Type> visited = Sets.newHashSet();

  /**
   * Visits the given types. Null types are ignored. This allows subclasses to call {@code
   * visit(parameterizedType.getOwnerType())} safely without having to check nulls.
   */
  public final void visit(Type... types) {
    for (Type type : types) {
      if (type == null || !visited.add(type)) {
        // null owner type, or already visited;
        continue;
      }
      boolean succeeded = false;
      try {
        if (type instanceof TypeVariable) {
          visitTypeVariable((TypeVariable<?>) type);
        } else if (type instanceof WildcardType) {
          visitWildcardType((WildcardType) type);
        } else if (type instanceof ParameterizedType) {
          visitParameterizedType((ParameterizedType) type);
        } else if (type instanceof Class) {
          visitClass((Class<?>) type);
        } else if (type instanceof GenericArrayType) {
          visitGenericArrayType((GenericArrayType) type);
        } else {
          throw new AssertionError("Unknown type: " + type);
        }
        succeeded = true;
      } finally {
        if (!succeeded) { // When the visitation failed, we don't want to ignore the second.
          visited.remove(type);
        }
      }
    }
  }

  void visitClass(Class<?> t) {}

  void visitGenericArrayType(GenericArrayType t) {}

  void visitParameterizedType(ParameterizedType t) {}

  void visitTypeVariable(TypeVariable<?> t) {}

  void visitWildcardType(WildcardType t) {}
}


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

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

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Comparator;
import sun.misc.Unsafe;

/**
 * Static utility methods pertaining to {@code byte} primitives that interpret values as
 * unsigned (that is, any negative value {@code b} is treated as the positive value {@code
 * 256 + b}). The corresponding methods that treat the values as signed are found in {@link
 * SignedBytes}, and the methods for which signedness is not an issue are in {@link Bytes}.
 *
 *
See the Guava User Guide article on primitive utilities.
 *
 * @author Kevin Bourrillion
 * @author Martin Buchholz
 * @author Hiroshi Yamauchi
 * @author Louis Wasserman
 * @since 1.0
 */
@GwtIncompatible
public final class UnsignedBytes {
  private UnsignedBytes() {}

  /**
   * The largest power of two that can be represented as an unsigned {@code byte}.
   *
   * @since 10.0
   */
  public static final byte MAX_POWER_OF_TWO = (byte) 0x80;

  /**
   * The largest value that fits into an unsigned byte.
   *
   * @since 13.0
   */
  public static final byte MAX_VALUE = (byte) 0xFF;

  private static final int UNSIGNED_MASK = 0xFF;

  /**
   * Returns the value of the given byte as an integer, when treated as unsigned. That is, returns
   * {@code value + 256} if {@code value} is negative; {@code value} itself otherwise.
   *
   *
Java 8 users: use {@link Byte#toUnsignedInt(byte)} instead.
   *
   * @since 6.0
   */
  public static int toInt(byte value) {
    return value & UNSIGNED_MASK;
  }

  /**
   * Returns the {@code byte} value that, when treated as unsigned, is equal to {@code value}, if
   * possible.
   *
   * @param value a value between 0 and 255 inclusive
   * @return the {@code byte} value that, when treated as unsigned, equals {@code value}
   * @throws IllegalArgumentException if {@code value} is negative or greater than 255
   */
  @CanIgnoreReturnValue
  public static byte checkedCast(long value) {
    checkArgument(value >> Byte.SIZE == 0, "out of range: %s", value);
    return (byte) value;
  }

  /**
   * Returns the {@code byte} value that, when treated as unsigned, is nearest in value to {@code
   * value}.
   *
   * @param value any {@code long} value
   * @return {@code (byte) 255} if {@code value >= 255}, {@code (byte) 0} if {@code value <= 0}, and
   *     {@code value} cast to {@code byte} otherwise
   */
  public static byte saturatedCast(long value) {
    if (value > toInt(MAX_VALUE)) {
      return MAX_VALUE; // -1
    }
    if (value < 0) {
      return (byte) 0;
    }
    return (byte) value;
  }

  /**
   * Compares the two specified {@code byte} values, treating them as unsigned values between 0 and
   * 255 inclusive. For example, {@code (byte) -127} is considered greater than {@code (byte) 127}
   * because it is seen as having the value of positive {@code 129}.
   *
   * @param a the first {@code byte} to compare
   * @param b the second {@code byte} to compare
   * @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is
   *     greater than {@code b}; or zero if they are equal
   */
  public static int compare(byte a, byte b) {
    return toInt(a) - toInt(b);
  }

  /**
   * Returns the least value present in {@code array}.
   *
   * @param array a nonempty array of {@code byte} values
   * @return the value present in {@code array} that is less than or equal to every other value in
   *     the array
   * @throws IllegalArgumentException if {@code array} is empty
   */
  public static byte min(byte... array) {
    checkArgument(array.length > 0);
    int min = toInt(array[0]);
    for (int i = 1; i < array.length; i++) {
      int next = toInt(array[i]);
      if (next < min) {
        min = next;
      }
    }
    return (byte) min;
  }

  /**
   * Returns the greatest value present in {@code array}.
   *
   * @param array a nonempty array of {@code byte} values
   * @return the value present in {@code array} that is greater than or equal to every other value
   *     in the array
   * @throws IllegalArgumentException if {@code array} is empty
   */
  public static byte max(byte... array) {
    checkArgument(array.length > 0);
    int max = toInt(array[0]);
    for (int i = 1; i < array.length; i++) {
      int next = toInt(array[i]);
      if (next > max) {
        max = next;
      }
    }
    return (byte) max;
  }

  /**
   * Returns a string representation of x, where x is treated as unsigned.
   *
   * @since 13.0
   */
  @Beta
  public static String toString(byte x) {
    return toString(x, 10);
  }

  /**
   * Returns a string representation of {@code x} for the given radix, where {@code x} is treated as
   * unsigned.
   *
   * @param x the value to convert to a string.
   * @param radix the radix to use while working with {@code x}
   * @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX}
   *     and {@link Character#MAX_RADIX}.
   * @since 13.0
   */
  @Beta
  public static String toString(byte x, int radix) {
    checkArgument(
        radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
        "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX",
        radix);
    // Benchmarks indicate this is probably not worth optimizing.
    return Integer.toString(toInt(x), radix);
  }

  /**
   * Returns the unsigned {@code byte} value represented by the given decimal string.
   *
   * @throws NumberFormatException if the string does not contain a valid unsigned {@code byte}
   *     value
   * @throws NullPointerException if {@code string} is null (in contrast to {@link
   *     Byte#parseByte(String)})
   * @since 13.0
   */
  @Beta
  @CanIgnoreReturnValue
  public static byte parseUnsignedByte(String string) {
    return parseUnsignedByte(string, 10);
  }

  /**
   * Returns the unsigned {@code byte} value represented by a string with the given radix.
   *
   * @param string the string containing the unsigned {@code byte} representation to be parsed.
   * @param radix the radix to use while parsing {@code string}
   * @throws NumberFormatException if the string does not contain a valid unsigned {@code byte} with
   *     the given radix, or if {@code radix} is not between {@link Character#MIN_RADIX} and {@link
   *     Character#MAX_RADIX}.
   * @throws NullPointerException if {@code string} is null (in contrast to {@link
   *     Byte#parseByte(String)})
   * @since 13.0
   */
  @Beta
  @CanIgnoreReturnValue
  public static byte parseUnsignedByte(String string, int radix) {
    int parse = Integer.parseInt(checkNotNull(string), radix);
    // We need to throw a NumberFormatException, so we have to duplicate checkedCast. =(
    if (parse >> Byte.SIZE == 0) {
      return (byte) parse;
    } else {
      throw new NumberFormatException("out of range: " + parse);
    }
  }

  /**
   * Returns a string containing the supplied {@code byte} values separated by {@code separator}.
   * For example, {@code join(":", (byte) 1, (byte) 2, (byte) 255)} returns the string {@code
   * "1:2:255"}.
   *
   * @param separator the text that should appear between consecutive values in the resulting string
   *     (but not at the start or end)
   * @param array an array of {@code byte} values, possibly empty
   */
  public static String join(String separator, byte... array) {
    checkNotNull(separator);
    if (array.length == 0) {
      return "";
    }

    // For pre-sizing a builder, just get the right order of magnitude
    StringBuilder builder = new StringBuilder(array.length * (3 + separator.length()));
    builder.append(toInt(array[0]));
    for (int i = 1; i < array.length; i++) {
      builder.append(separator).append(toString(array[i]));
    }
    return builder.toString();
  }

  /**
   * Returns a comparator that compares two {@code byte} arrays lexicographically. That is, it
   * compares, using {@link #compare(byte, byte)}), the first pair of values that follow any common
   * prefix, or when one array is a prefix of the other, treats the shorter array as the lesser. For
   * example, {@code [] < [0x01] < [0x01, 0x7F] < [0x01, 0x80] < [0x02]}. Values are treated as
   * unsigned.
   *
   *
The returned comparator is inconsistent with {@link Object#equals(Object)} (since arrays
   * support only identity equality), but it is consistent with {@link
   * java.util.Arrays#equals(byte[], byte[])}.
   *
   * @since 2.0
   */
  public static Comparator<byte[]> lexicographicalComparator() {
    return LexicographicalComparatorHolder.BEST_COMPARATOR;
  }

  @VisibleForTesting
  static Comparator<byte[]> lexicographicalComparatorJavaImpl() {
    return LexicographicalComparatorHolder.PureJavaComparator.INSTANCE;
  }

  /**
   * Provides a lexicographical comparator implementation; either a Java implementation or a faster
   * implementation based on {@link Unsafe}.
   *
   *
Uses reflection to gracefully fall back to the Java implementation if {@code Unsafe} isn't
   * available.
   */
  @VisibleForTesting
  static class LexicographicalComparatorHolder {
    static final String UNSAFE_COMPARATOR_NAME =
        LexicographicalComparatorHolder.class.getName() + "$UnsafeComparator";

    static final Comparator<byte[]> BEST_COMPARATOR = getBestComparator();

    @VisibleForTesting
    enum UnsafeComparator implements Comparator<byte[]> {
      INSTANCE;

      static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);

      /*
       * The following static final fields exist for performance reasons.
       *
       * In UnsignedBytesBenchmark, accessing the following objects via static final fields is the
       * fastest (more than twice as fast as the Java implementation, vs ~1.5x with non-final static
       * fields, on x86_32) under the Hotspot server compiler. The reason is obviously that the
       * non-final fields need to be reloaded inside the loop.
       *
       * And, no, defining (final or not) local variables out of the loop still isn't as good
       * because the null check on the theUnsafe object remains inside the loop and
       * BYTE_ARRAY_BASE_OFFSET doesn't get constant-folded.
       *
       * The compiler can treat static final fields as compile-time constants and can constant-fold
       * them while (final or not) local variables are run time values.
       */

      static final Unsafe theUnsafe = getUnsafe();

      /** The offset to the first element in a byte array. */
      static final int BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);

      static {
        // fall back to the safer pure java implementation unless we're in
        // a 64-bit JVM with an 8-byte aligned field offset.
        if (!("64".equals(System.getProperty("sun.arch.data.model"))
            && (BYTE_ARRAY_BASE_OFFSET % 8) == 0
            // sanity check - this should never fail
            && theUnsafe.arrayIndexScale(byte[].class) == 1)) {
          throw new Error(); // force fallback to PureJavaComparator
        }
      }

      /**
       * 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
       */
      private static sun.misc.Unsafe getUnsafe() {
        try {
          return sun.misc.Unsafe.getUnsafe();
        } catch (SecurityException e) {
          // that's okay; 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());
        }
      }

      @Override
      public int compare(byte[] left, byte[] right) {
        final int stride = 8;
        int minLength = Math.min(left.length, right.length);
        int strideLimit = minLength & ~(stride - 1);
        int i;

        /*
         * Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
         * than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
         */
        for (i = 0; i < strideLimit; i += stride) {
          long lw = theUnsafe.getLong(left, BYTE_ARRAY_BASE_OFFSET + (long) i);
          long rw = theUnsafe.getLong(right, BYTE_ARRAY_BASE_OFFSET + (long) i);
          if (lw != rw) {
            if (BIG_ENDIAN) {
              return UnsignedLongs.compare(lw, rw);
            }

            /*
             * We want to compare only the first index where left[index] != right[index]. This
             * corresponds to the least significant nonzero byte in lw ^ rw, since lw and rw are
             * little-endian. Long.numberOfTrailingZeros(diff) tells us the least significant
             * nonzero bit, and zeroing out the first three bits of L.nTZ gives us the shift to get
             * that least significant nonzero byte.
             */
            int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
            return ((int) ((lw >>> n) & UNSIGNED_MASK)) - ((int) ((rw >>> n) & UNSIGNED_MASK));
          }
        }

        // The epilogue to cover the last (minLength % stride) elements.
        for (; i < minLength; i++) {
          int result = UnsignedBytes.compare(left[i], right[i]);
          if (result != 0) {
            return result;
          }
        }
        return left.length - right.length;
      }

      @Override
      public String toString() {
        return "UnsignedBytes.lexicographicalComparator() (sun.misc.Unsafe version)";
      }
    }

    enum PureJavaComparator implements Comparator<byte[]> {
      INSTANCE;

      @Override
      public int compare(byte[] left, byte[] right) {
        int minLength = Math.min(left.length, right.length);
        for (int i = 0; i < minLength; i++) {
          int result = UnsignedBytes.compare(left[i], right[i]);
          if (result != 0) {
            return result;
          }
        }
        return left.length - right.length;
      }

      @Override
      public String toString() {
        return "UnsignedBytes.lexicographicalComparator() (pure Java version)";
      }
    }

    /**
     * Returns the Unsafe-using Comparator, or falls back to the pure-Java implementation if unable
     * to do so.
     */
    static Comparator<byte[]> getBestComparator() {
      try {
        Class<?> theClass = Class.forName(UNSAFE_COMPARATOR_NAME);

        // yes, UnsafeComparator does implement Comparator<byte[]>
        @SuppressWarnings("unchecked")
        Comparator<byte[]> comparator = (Comparator<byte[]>) theClass.getEnumConstants()[0];
        return comparator;
      } catch (Throwable t) { // ensure we really catch *everything*
        return lexicographicalComparatorJavaImpl();
      }
    }
  }

  private static byte flip(byte b) {
    return (byte) (b ^ 0x80);
  }

  /**
   * Sorts the array, treating its elements as unsigned bytes.
   *
   * @since 23.1
   */
  public static void sort(byte[] array) {
    checkNotNull(array);
    sort(array, 0, array.length);
  }

  /**
   * Sorts the array between {@code fromIndex} inclusive and {@code toIndex} exclusive, treating its
   * elements as unsigned bytes.
   *
   * @since 23.1
   */
  public static void sort(byte[] array, int fromIndex, int toIndex) {
    checkNotNull(array);
    checkPositionIndexes(fromIndex, toIndex, array.length);
    for (int i = fromIndex; i < toIndex; i++) {
      array[i] = flip(array[i]);
    }
    Arrays.sort(array, fromIndex, toIndex);
    for (int i = fromIndex; i < toIndex; i++) {
      array[i] = flip(array[i]);
    }
  }

  /**
   * Sorts the elements of {@code array} in descending order, interpreting them as unsigned 8-bit
   * integers.
   *
   * @since 23.1
   */
  public static void sortDescending(byte[] array) {
    checkNotNull(array);
    sortDescending(array, 0, array.length);
  }

  /**
   * Sorts the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex}
   * exclusive in descending order, interpreting them as unsigned 8-bit integers.
   *
   * @since 23.1
   */
  public static void sortDescending(byte[] array, int fromIndex, int toIndex) {
    checkNotNull(array);
    checkPositionIndexes(fromIndex, toIndex, array.length);
    for (int i = fromIndex; i < toIndex; i++) {
      array[i] ^= Byte.MAX_VALUE;
    }
    Arrays.sort(array, fromIndex, toIndex);
    for (int i = fromIndex; i < toIndex; i++) {
      array[i] ^= Byte.MAX_VALUE;
    }
  }
}


/*
 * Copyright (C) 2012 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 static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;

import com.google.common.primitives.Chars;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Abstract {@link Hasher} that handles converting primitives to bytes using a scratch {@code
 * ByteBuffer} and streams all bytes to a sink to compute the hash.
 *
 * @author Colin Decker
 */
@CanIgnoreReturnValue
abstract class AbstractByteHasher extends AbstractHasher {
  private final ByteBuffer scratch = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);

  /** Updates this hasher with the given byte. */
  protected abstract void update(byte b);

  /** Updates this hasher with the given bytes. */
  protected void update(byte[] b) {
    update(b, 0, b.length);
  }

  /** Updates this hasher with {@code len} bytes starting at {@code off} in the given buffer. */
  protected void update(byte[] b, int off, int len) {
    for (int i = off; i < off + len; i++) {
      update(b[i]);
    }
  }

  /** Updates this hasher with bytes from the given buffer. */
  protected void update(ByteBuffer b) {
    if (b.hasArray()) {
      update(b.array(), b.arrayOffset() + b.position(), b.remaining());
      b.position(b.limit());
    } else {
      for (int remaining = b.remaining(); remaining > 0; remaining--) {
        update(b.get());
      }
    }
  }

  /** Updates the sink with the given number of bytes from the buffer. */
  private Hasher update(int bytes) {
    try {
      update(scratch.array(), 0, bytes);
    } finally {
      scratch.clear();
    }
    return this;
  }

  @Override
  public Hasher putByte(byte b) {
    update(b);
    return this;
  }

  @Override
  public Hasher putBytes(byte[] bytes) {
    checkNotNull(bytes);
    update(bytes);
    return this;
  }

  @Override
  public Hasher putBytes(byte[] bytes, int off, int len) {
    checkPositionIndexes(off, off + len, bytes.length);
    update(bytes, off, len);
    return this;
  }

  @Override
  public Hasher putBytes(ByteBuffer bytes) {
    update(bytes);
    return this;
  }

  @Override
  public Hasher putShort(short s) {
    scratch.putShort(s);
    return update(Shorts.BYTES);
  }

  @Override
  public Hasher putInt(int i) {
    scratch.putInt(i);
    return update(Ints.BYTES);
  }

  @Override
  public Hasher putLong(long l) {
    scratch.putLong(l);
    return update(Longs.BYTES);
  }

  @Override
  public Hasher putChar(char c) {
    scratch.putChar(c);
    return update(Chars.BYTES);
  }
}


/*
 * 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.Beta;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collector;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * GWT emulation of {@link com.google.common.collect.ImmutableSortedSet}.
 *
 * @author Hayward Chan
 */
public abstract class ImmutableSortedSet<E> extends ForwardingImmutableSet<E>
    implements SortedSet<E>, SortedIterable<E> {
  // TODO(cpovirk): split into ImmutableSortedSet/ForwardingImmutableSortedSet?

  // In the non-emulated source, this is in ImmutableSortedSetFauxverideShim,
  // which overrides ImmutableSet & which ImmutableSortedSet extends.
  // It is necessary here because otherwise the builder() method
  // would be inherited from the emulated ImmutableSet.
  // TODO(cpovirk): should we be including other methods from the shim here and
  // in ImmutableSortedMap?
  @Deprecated
  public static <E> ImmutableSortedSet.Builder<E> builder() {
    throw new UnsupportedOperationException();
  }

  // TODO: Can we find a way to remove this @SuppressWarnings even for eclipse?
  @SuppressWarnings("unchecked")
  private static final Comparator NATURAL_ORDER = Ordering.natural();

  @SuppressWarnings("unchecked")
  private static final ImmutableSortedSet<Object> NATURAL_EMPTY_SET =
      new RegularImmutableSortedSet<Object>(new TreeSet<Object>(NATURAL_ORDER), false);

  static <E> ImmutableSortedSet<E> emptySet(Comparator<? super E> comparator) {
    checkNotNull(comparator);
    if (NATURAL_ORDER.equals(comparator)) {
      return of();
    } else {
      return new RegularImmutableSortedSet<E>(new TreeSet<E>(comparator), false);
    }
  }

  @Beta
  public static <E> Collector<E, ?, ImmutableSortedSet<E>> toImmutableSortedSet(
      Comparator<? super E> comparator) {
    return CollectCollectors.toImmutableSortedSet(comparator);
  }

  @SuppressWarnings("unchecked")
  public static <E> ImmutableSortedSet<E> of() {
    return (ImmutableSortedSet<E>) NATURAL_EMPTY_SET;
  }

  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E element) {
    return ofInternal(Ordering.natural(), element);
  }

  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2) {
    return ofInternal(Ordering.natural(), e1, e2);
  }

  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3) {
    return ofInternal(Ordering.natural(), e1, e2, e3);
  }

  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) {
    return ofInternal(Ordering.natural(), e1, e2, e3, e4);
  }

  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
      E e1, E e2, E e3, E e4, E e5) {
    return ofInternal(Ordering.natural(), e1, e2, e3, e4, e5);
  }

  @SuppressWarnings("unchecked")
  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(
      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
    int size = remaining.length + 6;
    List<E> all = new ArrayList<E>(size);
    Collections.addAll(all, e1, e2, e3, e4, e5, e6);
    Collections.addAll(all, remaining);
    // This is messed up. See TODO at top of file.
    return ofInternal(Ordering.natural(), (E[]) all.toArray(new Comparable[0]));
  }

  private static <E> ImmutableSortedSet<E> ofInternal(
      Comparator<? super E> comparator, E... elements) {
    checkNotNull(elements);
    switch (elements.length) {
      case 0:
        return emptySet(comparator);
      default:
        SortedSet<E> delegate = new TreeSet<E>(comparator);
        for (E element : elements) {
          checkNotNull(element);
          delegate.add(element);
        }
        return new RegularImmutableSortedSet<E>(delegate, false);
    }
  }

  public static <E> ImmutableSortedSet<E> copyOf(Collection<? extends E> elements) {
    return copyOfInternal((Ordering<E>) Ordering.natural(), (Collection) elements, false);
  }

  public static <E> ImmutableSortedSet<E> copyOf(Iterable<? extends E> elements) {
    return copyOfInternal((Ordering<E>) Ordering.natural(), (Iterable) elements, false);
  }

  public static <E> ImmutableSortedSet<E> copyOf(Iterator<? extends E> elements) {
    return copyOfInternal((Ordering<E>) Ordering.natural(), (Iterator) elements);
  }

  public static <E extends Comparable<? super E>> ImmutableSortedSet<E> copyOf(E[] elements) {
    return ofInternal(Ordering.natural(), elements);
  }

  public static <E> ImmutableSortedSet<E> copyOf(
      Comparator<? super E> comparator, Iterable<? extends E> elements) {
    checkNotNull(comparator);
    return copyOfInternal(comparator, elements, false);
  }

  public static <E> ImmutableSortedSet<E> copyOf(
      Comparator<? super E> comparator, Collection<? extends E> elements) {
    checkNotNull(comparator);
    return copyOfInternal(comparator, elements, false);
  }

  public static <E> ImmutableSortedSet<E> copyOf(
      Comparator<? super E> comparator, Iterator<? extends E> elements) {
    checkNotNull(comparator);
    return copyOfInternal(comparator, elements);
  }

  @SuppressWarnings("unchecked")
  public static <E> ImmutableSortedSet<E> copyOfSorted(SortedSet<E> sortedSet) {
    Comparator<? super E> comparator = sortedSet.comparator();
    if (comparator == null) {
      comparator = NATURAL_ORDER;
    }
    return copyOfInternal(comparator, sortedSet.iterator());
  }

  private static <E> ImmutableSortedSet<E> copyOfInternal(
      Comparator<? super E> comparator, Iterable<? extends E> elements, boolean fromSortedSet) {
    checkNotNull(comparator);

    boolean hasSameComparator = fromSortedSet || hasSameComparator(elements, comparator);
    if (hasSameComparator && (elements instanceof ImmutableSortedSet)) {
      @SuppressWarnings("unchecked")
      ImmutableSortedSet<E> result = (ImmutableSortedSet<E>) elements;
      boolean isSubset =
          (result instanceof RegularImmutableSortedSet)
              && ((RegularImmutableSortedSet) result).isSubset;
      if (!isSubset) {
        // Only return the original copy if this immutable sorted set isn't
        // a subset of another, to avoid memory leak.
        return result;
      }
    }
    return copyOfInternal(comparator, elements.iterator());
  }

  private static <E> ImmutableSortedSet<E> copyOfInternal(
      Comparator<? super E> comparator, Iterator<? extends E> elements) {
    checkNotNull(comparator);
    if (!elements.hasNext()) {
      return emptySet(comparator);
    }
    SortedSet<E> delegate = new TreeSet<E>(comparator);
    while (elements.hasNext()) {
      E element = elements.next();
      checkNotNull(element);
      delegate.add(element);
    }
    return new RegularImmutableSortedSet<E>(delegate, false);
  }

  private static boolean hasSameComparator(Iterable<?> elements, Comparator<?> comparator) {
    if (elements instanceof SortedSet) {
      SortedSet<?> sortedSet = (SortedSet<?>) elements;
      Comparator<?> comparator2 = sortedSet.comparator();
      return (comparator2 == null)
          ? comparator == Ordering.natural()
          : comparator.equals(comparator2);
    }
    return false;
  }

  // Assumes that delegate doesn't have null elements and comparator.
  static <E> ImmutableSortedSet<E> unsafeDelegateSortedSet(
      SortedSet<E> delegate, boolean isSubset) {
    return delegate.isEmpty()
        ? emptySet(delegate.comparator())
        : new RegularImmutableSortedSet<E>(delegate, isSubset);
  }

  private final transient SortedSet<E> sortedDelegate;

  /**
   * Scary constructor for ContiguousSet. This constructor (in this file, the GWT emulation of
   * ImmutableSortedSet) creates an empty sortedDelegate, which, in a vacuum, sets this object's
   * contents to empty. By contrast, the non-GWT constructor with the same signature uses the
   * comparator only as a comparator. It does NOT assume empty contents. (It requires an
   * implementation of iterator() to define its contents, and methods like contains() are
   * implemented in terms of that method (though they will likely be overridden by subclasses for
   * performance reasons).) This means that a call to this method have can different behavior in GWT
   * and non-GWT environments UNLESS subclasses are careful to always override all methods
   * implemented in terms of sortedDelegate (except comparator()).
   */
  ImmutableSortedSet(Comparator<? super E> comparator) {
    this(Sets.newTreeSet(comparator));
  }

  ImmutableSortedSet(SortedSet<E> sortedDelegate) {
    super(sortedDelegate);
    this.sortedDelegate = Collections.unmodifiableSortedSet(sortedDelegate);
  }

  public Comparator<? super E> comparator() {
    return sortedDelegate.comparator();
  }

  @Override // needed to unify SortedIterable and Collection iterator() methods
  public UnmodifiableIterator<E> iterator() {
    return super.iterator();
  }

  @Override
  public Object[] toArray() {
    return ObjectArrays.toArrayImpl(this);
  }

  @Override
  public <T> T[] toArray(T[] other) {
    return ObjectArrays.toArrayImpl(this, other);
  }

  @Override
  public boolean contains(@Nullable Object object) {
    try {
      // This set never contains null.  We need to explicitly check here
      // because some comparator might throw NPE (e.g. the natural ordering).
      return object != null && sortedDelegate.contains(object);
    } catch (ClassCastException e) {
      return false;
    }
  }

  @Override
  public boolean containsAll(Collection<?> targets) {
    for (Object target : targets) {
      if (target == null) {
        // This set never contains null.  We need to explicitly check here
        // because some comparator might throw NPE (e.g. the natural ordering).
        return false;
      }
    }
    try {
      return sortedDelegate.containsAll(targets);
    } catch (ClassCastException e) {
      return false;
    }
  }

  public E first() {
    return sortedDelegate.first();
  }

  public ImmutableSortedSet<E> headSet(E toElement) {
    checkNotNull(toElement);
    try {
      return unsafeDelegateSortedSet(sortedDelegate.headSet(toElement), true);
    } catch (IllegalArgumentException e) {
      return emptySet(comparator());
    }
  }

  E higher(E e) {
    checkNotNull(e);
    Iterator<E> iterator = tailSet(e).iterator();
    while (iterator.hasNext()) {
      E higher = iterator.next();
      if (comparator().compare(e, higher) < 0) {
        return higher;
      }
    }
    return null;
  }

  ImmutableSortedSet<E> headSet(E toElement, boolean inclusive) {
    checkNotNull(toElement);
    if (inclusive) {
      E tmp = higher(toElement);
      if (tmp == null) {
        return this;
      }
      toElement = tmp;
    }
    return headSet(toElement);
  }

  public E last() {
    return sortedDelegate.last();
  }

  public ImmutableSortedSet<E> subSet(E fromElement, E toElement) {
    return subSet(fromElement, true, toElement, false);
  }

  ImmutableSortedSet<E> subSet(
      E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
    checkNotNull(fromElement);
    checkNotNull(toElement);
    int cmp = comparator().compare(fromElement, toElement);
    checkArgument(cmp <= 0, "fromElement (%s) is less than toElement (%s)", fromElement, toElement);
    if (cmp == 0 && !(fromInclusive && toInclusive)) {
      return emptySet(comparator());
    }
    return tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive);
  }

  public ImmutableSortedSet<E> tailSet(E fromElement) {
    checkNotNull(fromElement);
    try {
      return unsafeDelegateSortedSet(sortedDelegate.tailSet(fromElement), true);
    } catch (IllegalArgumentException e) {
      return emptySet(comparator());
    }
  }

  ImmutableSortedSet<E> tailSet(E fromElement, boolean inclusive) {
    checkNotNull(fromElement);
    if (!inclusive) {
      E tmp = higher(fromElement);
      if (tmp == null) {
        return emptySet(comparator());
      }
      fromElement = tmp;
    }
    return tailSet(fromElement);
  }

  public static <E> Builder<E> orderedBy(Comparator<E> comparator) {
    return new Builder<E>(comparator);
  }

  public static <E extends Comparable<?>> Builder<E> reverseOrder() {
    return new Builder<E>(Ordering.natural().reverse());
  }

  public static <E extends Comparable<?>> Builder<E> naturalOrder() {
    return new Builder<E>(Ordering.natural());
  }

  public static final class Builder<E> extends ImmutableSet.Builder<E> {
    private final Comparator<? super E> comparator;

    public Builder(Comparator<? super E> comparator) {
      this.comparator = checkNotNull(comparator);
    }

    @Override
    public Builder<E> add(E element) {
      super.add(element);
      return this;
    }

    @Override
    public Builder<E> add(E... elements) {
      super.add(elements);
      return this;
    }

    @Override
    public Builder<E> addAll(Iterable<? extends E> elements) {
      super.addAll(elements);
      return this;
    }

    @Override
    public Builder<E> addAll(Iterator<? extends E> elements) {
      super.addAll(elements);
      return this;
    }

    Builder<E> combine(Builder<E> builder) {
      super.combine(builder);
      return this;
    }

    @Override
    public ImmutableSortedSet<E> build() {
      return copyOfInternal(comparator, contents.iterator());
    }
  }
}


/*
 * 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 com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
import java.util.Comparator;

/**
 * This class implements the GWT serialization of {@link ImmutableSetMultimap}.
 *
 * @author Chris Povirk
 */
public class ImmutableSetMultimap_CustomFieldSerializer {

  public static void deserialize(
      SerializationStreamReader reader, ImmutableSetMultimap<?, ?> instance) {}

  // Serialization type safety is at the caller's mercy.
  @SuppressWarnings("unchecked")
  public static ImmutableSetMultimap<Object, Object> instantiate(SerializationStreamReader reader)
      throws SerializationException {
    Comparator<Object> valueComparator = (Comparator<Object>) reader.readObject();
    ImmutableSetMultimap.Builder<Object, Object> builder = ImmutableSetMultimap.builder();
    if (valueComparator != null) {
      builder.orderValuesBy(valueComparator);
    }
    return (ImmutableSetMultimap<Object, Object>)
        Multimap_CustomFieldSerializerBase.instantiate(reader, builder);
  }

  public static void serialize(
      SerializationStreamWriter writer, ImmutableSetMultimap<?, ?> instance)
      throws SerializationException {
    writer.writeObject(instance.valueComparator());
    Multimap_CustomFieldSerializerBase.serialize(writer, instance);
  }
}


/*
 * 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.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.base.Function;
import com.google.common.collect.Maps;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Serializable;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import org.checkerframework.checker.nullness.compatqual.MonotonicNonNullDecl;

/**
 * A map containing {@code long} values that can be atomically updated. While writes to a
 * traditional {@code Map} rely on {@code put(K, V)}, the typical mechanism for writing to this map
 * is {@code addAndGet(K, long)}, which adds a {@code long} to the value currently associated with
 * {@code K}. If a key has not yet been associated with a value, its implicit value is zero.
 *
 *
Most methods in this class treat absent values and zero values identically, as individually
 * documented. Exceptions to this are {@link #containsKey}, {@link #size}, {@link #isEmpty}, {@link
 * #asMap}, and {@link #toString}.
 *
 *
Instances of this class may be used by multiple threads concurrently. All operations are
 * atomic unless otherwise noted.
 *
 *
Note: If your values are always positive and less than 2^31, you may wish to use a
 * {@link com.google.common.collect.Multiset} such as {@link
 * com.google.common.collect.ConcurrentHashMultiset} instead.
 *
 *
Warning: Unlike {@code Multiset}, entries whose values are zero are not automatically
 * removed from the map. Instead they must be removed manually with {@link #removeAllZeros}.
 *
 * @author Charles Fry
 * @since 11.0
 */
@GwtCompatible
public final class AtomicLongMap<K> implements Serializable {
  private final ConcurrentHashMap<K, AtomicLong> map;

  private AtomicLongMap(ConcurrentHashMap<K, AtomicLong> map) {
    this.map = checkNotNull(map);
  }

  /** Creates an {@code AtomicLongMap}. */
  public static <K> AtomicLongMap<K> create() {
    return new AtomicLongMap<K>(new ConcurrentHashMap<K, AtomicLong>());
  }

  /** Creates an {@code AtomicLongMap} with the same mappings as the specified {@code Map}. */
  public static <K> AtomicLongMap<K> create(Map<? extends K, ? extends Long> m) {
    AtomicLongMap<K> result = create();
    result.putAll(m);
    return result;
  }

  /**
   * Returns the value associated with {@code key}, or zero if there is no value associated with
   * {@code key}.
   */
  public long get(K key) {
    AtomicLong atomic = map.get(key);
    return atomic == null ? 0L : atomic.get();
  }

  /**
   * Increments by one the value currently associated with {@code key}, and returns the new value.
   */
  @CanIgnoreReturnValue
  public long incrementAndGet(K key) {
    return addAndGet(key, 1);
  }

  /**
   * Decrements by one the value currently associated with {@code key}, and returns the new value.
   */
  @CanIgnoreReturnValue
  public long decrementAndGet(K key) {
    return addAndGet(key, -1);
  }

  /**
   * Adds {@code delta} to the value currently associated with {@code key}, and returns the new
   * value.
   */
  @CanIgnoreReturnValue
  public long addAndGet(K key, long delta) {
    outer:
    while (true) {
      AtomicLong atomic = map.get(key);
      if (atomic == null) {
        atomic = map.putIfAbsent(key, new AtomicLong(delta));
        if (atomic == null) {
          return delta;
        }
        // atomic is now non-null; fall through
      }

      while (true) {
        long oldValue = atomic.get();
        if (oldValue == 0L) {
          // don't compareAndSet a zero
          if (map.replace(key, atomic, new AtomicLong(delta))) {
            return delta;
          }
          // atomic replaced
          continue outer;
        }

        long newValue = oldValue + delta;
        if (atomic.compareAndSet(oldValue, newValue)) {
          return newValue;
        }
        // value changed
      }
    }
  }

  /**
   * Increments by one the value currently associated with {@code key}, and returns the old value.
   */
  @CanIgnoreReturnValue
  public long getAndIncrement(K key) {
    return getAndAdd(key, 1);
  }

  /**
   * Decrements by one the value currently associated with {@code key}, and returns the old value.
   */
  @CanIgnoreReturnValue
  public long getAndDecrement(K key) {
    return getAndAdd(key, -1);
  }

  /**
   * Adds {@code delta} to the value currently associated with {@code key}, and returns the old
   * value.
   */
  @CanIgnoreReturnValue
  public long getAndAdd(K key, long delta) {
    outer:
    while (true) {
      AtomicLong atomic = map.get(key);
      if (atomic == null) {
        atomic = map.putIfAbsent(key, new AtomicLong(delta));
        if (atomic == null) {
          return 0L;
        }
        // atomic is now non-null; fall through
      }

      while (true) {
        long oldValue = atomic.get();
        if (oldValue == 0L) {
          // don't compareAndSet a zero
          if (map.replace(key, atomic, new AtomicLong(delta))) {
            return 0L;
          }
          // atomic replaced
          continue outer;
        }

        long newValue = oldValue + delta;
        if (atomic.compareAndSet(oldValue, newValue)) {
          return oldValue;
        }
        // value changed
      }
    }
  }

  /**
   * Associates {@code newValue} with {@code key} in this map, and returns the value previously
   * associated with {@code key}, or zero if there was no such value.
   */
  @CanIgnoreReturnValue
  public long put(K key, long newValue) {
    outer:
    while (true) {
      AtomicLong atomic = map.get(key);
      if (atomic == null) {
        atomic = map.putIfAbsent(key, new AtomicLong(newValue));
        if (atomic == null) {
          return 0L;
        }
        // atomic is now non-null; fall through
      }

      while (true) {
        long oldValue = atomic.get();
        if (oldValue == 0L) {
          // don't compareAndSet a zero
          if (map.replace(key, atomic, new AtomicLong(newValue))) {
            return 0L;
          }
          // atomic replaced
          continue outer;
        }

        if (atomic.compareAndSet(oldValue, newValue)) {
          return oldValue;
        }
        // value changed
      }
    }
  }

  /**
   * Copies all of the mappings from the specified map to this map. The effect of this call is
   * equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key
   * {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined
   * if the specified map is modified while the operation is in progress.
   */
  public void putAll(Map<? extends K, ? extends Long> m) {
    for (Entry<? extends K, ? extends Long> entry : m.entrySet()) {
      put(entry.getKey(), entry.getValue());
    }
  }

  /**
   * Removes and returns the value associated with {@code key}. If {@code key} is not in the map,
   * this method has no effect and returns zero.
   */
  @CanIgnoreReturnValue
  public long remove(K key) {
    AtomicLong atomic = map.get(key);
    if (atomic == null) {
      return 0L;
    }

    while (true) {
      long oldValue = atomic.get();
      if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
        // only remove after setting to zero, to avoid concurrent updates
        map.remove(key, atomic);
        // succeed even if the remove fails, since the value was already adjusted
        return oldValue;
      }
    }
  }

  /**
   * If {@code (key, value)} is currently in the map, this method removes it and returns true;
   * otherwise, this method returns false.
   */
  boolean remove(K key, long value) {
    AtomicLong atomic = map.get(key);
    if (atomic == null) {
      return false;
    }

    long oldValue = atomic.get();
    if (oldValue != value) {
      return false;
    }

    if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
      // only remove after setting to zero, to avoid concurrent updates
      map.remove(key, atomic);
      // succeed even if the remove fails, since the value was already adjusted
      return true;
    }

    // value changed
    return false;
  }

  /**
   * Atomically remove {@code key} from the map iff its associated value is 0.
   *
   * @since 20.0
   */
  @Beta
  @CanIgnoreReturnValue
  public boolean removeIfZero(K key) {
    return remove(key, 0);
  }

  /**
   * Removes all mappings from this map whose values are zero.
   *
   *
This method is not atomic: the map may be visible in intermediate states, where some of the
   * zero values have been removed and others have not.
   */
  public void removeAllZeros() {
    Iterator<Entry<K, AtomicLong>> entryIterator = map.entrySet().iterator();
    while (entryIterator.hasNext()) {
      Entry<K, AtomicLong> entry = entryIterator.next();
      AtomicLong atomic = entry.getValue();
      if (atomic != null && atomic.get() == 0L) {
        entryIterator.remove();
      }
    }
  }

  /**
   * Returns the sum of all values in this map.
   *
   *
This method is not atomic: the sum may or may not include other concurrent operations.
   */
  public long sum() {
    long sum = 0L;
    for (AtomicLong value : map.values()) {
      sum = sum + value.get();
    }
    return sum;
  }

  @MonotonicNonNullDecl private transient Map<K, Long> asMap;

  /** Returns a live, read-only view of the map backing this {@code AtomicLongMap}. */
  public Map<K, Long> asMap() {
    Map<K, Long> result = asMap;
    return (result == null) ? asMap = createAsMap() : result;
  }

  private Map<K, Long> createAsMap() {
    return Collections.unmodifiableMap(
        Maps.transformValues(
            map,
            new Function<AtomicLong, Long>() {
              @Override
              public Long apply(AtomicLong atomic) {
                return atomic.get();
              }
            }));
  }

  /** Returns true if this map contains a mapping for the specified key. */
  public boolean containsKey(Object key) {
    return map.containsKey(key);
  }

  /**
   * Returns the number of key-value mappings in this map. If the map contains more than {@code
   * Integer.MAX_VALUE} elements, returns {@code Integer.MAX_VALUE}.
   */
  public int size() {
    return map.size();
  }

  /** Returns {@code true} if this map contains no key-value mappings. */
  public boolean isEmpty() {
    return map.isEmpty();
  }

  /**
   * Removes all of the mappings from this map. The map will be empty after this call returns.
   *
   *
This method is not atomic: the map may not be empty after returning if there were concurrent
   * writes.
   */
  public void clear() {
    map.clear();
  }

  @Override
  public String toString() {
    return map.toString();
  }

  /*
   * ConcurrentMap operations which we may eventually add.
   *
   * The problem with these is that remove(K, long) has to be done in two phases by definition ---
   * first decrementing to zero, and then removing. putIfAbsent or replace could observe the
   * intermediate zero-state. Ways we could deal with this are:
   *
   * - Don't define any of the ConcurrentMap operations. This is the current state of affairs.
   *
   * - Define putIfAbsent and replace as treating zero and absent identically (as currently
   *   implemented below). This is a bit surprising with putIfAbsent, which really becomes
   *   putIfZero.
   *
   * - Allow putIfAbsent and replace to distinguish between zero and absent, but don't implement
   *   remove(K, long). Without any two-phase operations it becomes feasible for all remaining
   *   operations to distinguish between zero and absent. If we do this, then perhaps we should add
   *   replace(key, long).
   *
   * - Introduce a special-value private static final AtomicLong that would have the meaning of
   *   removal-in-progress, and rework all operations to properly distinguish between zero and
   *   absent.
   */

  /**
   * If {@code key} is not already associated with a value or if {@code key} is associated with
   * zero, associate it with {@code newValue}. Returns the previous value associated with {@code
   * key}, or zero if there was no mapping for {@code key}.
   */
  long putIfAbsent(K key, long newValue) {
    while (true) {
      AtomicLong atomic = map.get(key);
      if (atomic == null) {
        atomic = map.putIfAbsent(key, new AtomicLong(newValue));
        if (atomic == null) {
          return 0L;
        }
        // atomic is now non-null; fall through
      }

      long oldValue = atomic.get();
      if (oldValue == 0L) {
        // don't compareAndSet a zero
        if (map.replace(key, atomic, new AtomicLong(newValue))) {
          return 0L;
        }
        // atomic replaced
        continue;
      }

      return oldValue;
    }
  }

  /**
   * If {@code (key, expectedOldValue)} is currently in the map, this method replaces {@code
   * expectedOldValue} with {@code newValue} and returns true; otherwise, this method returns false.
   *
   *
If {@code expectedOldValue} is zero, this method will succeed if {@code (key, zero)} is
   * currently in the map, or if {@code key} is not in the map at all.
   */
  boolean replace(K key, long expectedOldValue, long newValue) {
    if (expectedOldValue == 0L) {
      return putIfAbsent(key, newValue) == 0L;
    } else {
      AtomicLong atomic = map.get(key);
      return (atomic == null) ? false : atomic.compareAndSet(expectedOldValue, newValue);
    }
  }
}


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

import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A reference queue with an associated background thread that dequeues references and invokes
 * {@link FinalizableReference#finalizeReferent()} on them.
 *
 *
Keep a strong reference to this object until all of the associated referents have been
 * finalized. If this object is garbage collected earlier, the backing thread will not invoke {@code
 * finalizeReferent()} on the remaining references.
 *
 *
As an example of how this is used, imagine you have a class {@code MyServer} that creates a a
 * {@link java.net.ServerSocket ServerSocket}, and you would like to ensure that the {@code
 * ServerSocket} is closed even if the {@code MyServer} object is garbage-collected without calling
 * its {@code close} method. You could use a finalizer to accomplish this, but that has a
 * number of well-known problems. Here is how you might use this class instead:
 *
 *
{@code
 * public class MyServer implements Closeable {
 *   private static final FinalizableReferenceQueue frq = new FinalizableReferenceQueue();
 *   // You might also share this between several objects.
 *
 *   private static final Set<Reference<?>> references = Sets.newConcurrentHashSet();
 *   // This ensures that the FinalizablePhantomReference itself is not garbage-collected.
 *
 *   private final ServerSocket serverSocket;
 *
 *   private MyServer(...) {
 *     ...
 *     this.serverSocket = new ServerSocket(...);
 *     ...
 *   }
 *
 *   public static MyServer create(...) {
 *     MyServer myServer = new MyServer(...);
 *     final ServerSocket serverSocket = myServer.serverSocket;
 *     Reference<?> reference = new FinalizablePhantomReference<MyServer>(myServer, frq) {
 *       public void finalizeReferent() {
 *         references.remove(this):
 *         if (!serverSocket.isClosed()) {
 *           ...log a message about how nobody called close()...
 *           try {
 *             serverSocket.close();
 *           } catch (IOException e) {
 *             ...
 *           }
 *         }
 *       }
 *     };
 *     references.add(reference);
 *     return myServer;
 *   }
 *
 *   public void close() {
 *     serverSocket.close();
 *   }
 * }
 * }

 *
 * @author Bob Lee
 * @since 2.0
 */
@GwtIncompatible
public class FinalizableReferenceQueue implements Closeable {
  /*
   * The Finalizer thread keeps a phantom reference to this object. When the client (for example, a
   * map built by MapMaker) no longer has a strong reference to this object, the garbage collector
   * will reclaim it and enqueue the phantom reference. The enqueued reference will trigger the
   * Finalizer to stop.
   *
   * If this library is loaded in the system class loader, FinalizableReferenceQueue can load
   * Finalizer directly with no problems.
   *
   * If this library is loaded in an application class loader, it's important that Finalizer not
   * have a strong reference back to the class loader. Otherwise, you could have a graph like this:
   *
   * Finalizer Thread runs instance of -> Finalizer.class loaded by -> Application class loader
   * which loaded -> ReferenceMap.class which has a static -> FinalizableReferenceQueue instance
   *
   * Even if no other references to classes from the application class loader remain, the Finalizer
   * thread keeps an indirect strong reference to the queue in ReferenceMap, which keeps the
   * Finalizer running, and as a result, the application class loader can never be reclaimed.
   *
   * This means that dynamically loaded web applications and OSGi bundles can't be unloaded.
   *
   * If the library is loaded in an application class loader, we try to break the cycle by loading
   * Finalizer in its own independent class loader:
   *
   * System class loader -> Application class loader -> ReferenceMap -> FinalizableReferenceQueue ->
   * etc. -> Decoupled class loader -> Finalizer
   *
   * Now, Finalizer no longer keeps an indirect strong reference to the static
   * FinalizableReferenceQueue field in ReferenceMap. The application class loader can be reclaimed
   * at which point the Finalizer thread will stop and its decoupled class loader can also be
   * reclaimed.
   *
   * If any of this fails along the way, we fall back to loading Finalizer directly in the
   * application class loader.
   *
   * NOTE: The tests for this behavior (FinalizableReferenceQueueClassLoaderUnloadingTest) fail
   * strangely when run in JDK 9. We are considering this a known issue. Please see
   * https://github.com/google/guava/issues/3086 for more information.
   */

  private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName());

  private static final String FINALIZER_CLASS_NAME = "com.google.common.base.internal.Finalizer";

  /** Reference to Finalizer.startFinalizer(). */
  private static final Method startFinalizer;

  static {
    Class<?> finalizer =
        loadFinalizer(new SystemLoader(), new DecoupledLoader(), new DirectLoader());
    startFinalizer = getStartFinalizer(finalizer);
  }

  /** The actual reference queue that our background thread will poll. */
  final ReferenceQueue<Object> queue;

  final PhantomReference<Object> frqRef;

  /** Whether or not the background thread started successfully. */
  final boolean threadStarted;

  /** Constructs a new queue. */
  public FinalizableReferenceQueue() {
    // We could start the finalizer lazily, but I'd rather it blow up early.
    queue = new ReferenceQueue<>();
    frqRef = new PhantomReference<Object>(this, queue);
    boolean threadStarted = false;
    try {
      startFinalizer.invoke(null, FinalizableReference.class, queue, frqRef);
      threadStarted = true;
    } catch (IllegalAccessException impossible) {
      throw new AssertionError(impossible); // startFinalizer() is public
    } catch (Throwable t) {
      logger.log(
          Level.INFO,
          "Failed to start reference finalizer thread."
              + " Reference cleanup will only occur when new references are created.",
          t);
    }

    this.threadStarted = threadStarted;
  }

  @Override
  public void close() {
    frqRef.enqueue();
    cleanUp();
  }

  /**
   * Repeatedly dequeues references from the queue and invokes {@link
   * FinalizableReference#finalizeReferent()} on them until the queue is empty. This method is a
   * no-op if the background thread was created successfully.
   */
  void cleanUp() {
    if (threadStarted) {
      return;
    }

    Reference<?> reference;
    while ((reference = queue.poll()) != null) {
      /*
       * This is for the benefit of phantom references. Weak and soft references will have already
       * been cleared by this point.
       */
      reference.clear();
      try {
        ((FinalizableReference) reference).finalizeReferent();
      } catch (Throwable t) {
        logger.log(Level.SEVERE, "Error cleaning up after reference.", t);
      }
    }
  }

  /**
   * Iterates through the given loaders until it finds one that can load Finalizer.
   *
   * @return Finalizer.class
   */
  private static Class<?> loadFinalizer(FinalizerLoader... loaders) {
    for (FinalizerLoader loader : loaders) {
      Class<?> finalizer = loader.loadFinalizer();
      if (finalizer != null) {
        return finalizer;
      }
    }

    throw new AssertionError();
  }

  /** Loads Finalizer.class. */
  interface FinalizerLoader {

    /**
     * Returns Finalizer.class or null if this loader shouldn't or can't load it.
     *
     * @throws SecurityException if we don't have the appropriate privileges
     */
    @Nullable
    Class<?> loadFinalizer();
  }

  /**
   * Tries to load Finalizer from the system class loader. If Finalizer is in the system class path,
   * we needn't create a separate loader.
   */
  static class SystemLoader implements FinalizerLoader {
    // This is used by the ClassLoader-leak test in FinalizableReferenceQueueTest to disable
    // finding Finalizer on the system class path even if it is there.
    @VisibleForTesting static boolean disabled;

    @Override
    public @Nullable Class<?> loadFinalizer() {
      if (disabled) {
        return null;
      }
      ClassLoader systemLoader;
      try {
        systemLoader = ClassLoader.getSystemClassLoader();
      } catch (SecurityException e) {
        logger.info("Not allowed to access system class loader.");
        return null;
      }
      if (systemLoader != null) {
        try {
          return systemLoader.loadClass(FINALIZER_CLASS_NAME);
        } catch (ClassNotFoundException e) {
          // Ignore. Finalizer is simply in a child class loader.
          return null;
        }
      } else {
        return null;
      }
    }
  }

  /**
   * Try to load Finalizer in its own class loader. If Finalizer's thread had a direct reference to
   * our class loader (which could be that of a dynamically loaded web application or OSGi bundle),
   * it would prevent our class loader from getting garbage collected.
   */
  static class DecoupledLoader implements FinalizerLoader {
    private static final String LOADING_ERROR =
        "Could not load Finalizer in its own class loader. Loading Finalizer in the current class "
            + "loader instead. As a result, you will not be able to garbage collect this class "
            + "loader. To support reclaiming this class loader, either resolve the underlying "
            + "issue, or move Guava to your system class path.";

    @Override
    public @Nullable Class<?> loadFinalizer() {
      try {
        /*
         * We use URLClassLoader because it's the only concrete class loader implementation in the
         * JDK. If we used our own ClassLoader subclass, Finalizer would indirectly reference this
         * class loader:
         *
         * Finalizer.class -> CustomClassLoader -> CustomClassLoader.class -> This class loader
         *
         * System class loader will (and must) be the parent.
         */
        ClassLoader finalizerLoader = newLoader(getBaseUrl());
        return finalizerLoader.loadClass(FINALIZER_CLASS_NAME);
      } catch (Exception e) {
        logger.log(Level.WARNING, LOADING_ERROR, e);
        return null;
      }
    }

    /** Gets URL for base of path containing Finalizer.class. */
    URL getBaseUrl() throws IOException {
      // Find URL pointing to Finalizer.class file.
      String finalizerPath = FINALIZER_CLASS_NAME.replace('.', '/') + ".class";
      URL finalizerUrl = getClass().getClassLoader().getResource(finalizerPath);
      if (finalizerUrl == null) {
        throw new FileNotFoundException(finalizerPath);
      }

      // Find URL pointing to base of class path.
      String urlString = finalizerUrl.toString();
      if (!urlString.endsWith(finalizerPath)) {
        throw new IOException("Unsupported path style: " + urlString);
      }
      urlString = urlString.substring(0, urlString.length() - finalizerPath.length());
      return new URL(finalizerUrl, urlString);
    }

    /** Creates a class loader with the given base URL as its classpath. */
    URLClassLoader newLoader(URL base) {
      // We use the bootstrap class loader as the parent because Finalizer by design uses
      // only standard Java classes. That also means that FinalizableReferenceQueueTest
      // doesn't pick up the wrong version of the Finalizer class.
      return new URLClassLoader(new URL[] {base}, null);
    }
  }

  /**
   * Loads Finalizer directly using the current class loader. We won't be able to garbage collect
   * this class loader, but at least the world doesn't end.
   */
  static class DirectLoader implements FinalizerLoader {
    @Override
    public Class<?> loadFinalizer() {
      try {
        return Class.forName(FINALIZER_CLASS_NAME);
      } catch (ClassNotFoundException e) {
        throw new AssertionError(e);
      }
    }
  }

  /** Looks up Finalizer.startFinalizer(). */
  static Method getStartFinalizer(Class<?> finalizer) {
    try {
      return finalizer.getMethod(
          "startFinalizer", Class.class, ReferenceQueue.class, PhantomReference.class);
    } catch (NoSuchMethodException e) {
      throw new AssertionError(e);
    }
  }
}


/*
 * Copyright (C) 2012 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.Beta;
import com.google.common.annotations.GwtIncompatible;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.SortedSet;

/**
 * A navigable set which forwards all its method calls to another navigable set. Subclasses should
 * override one or more methods to modify the behavior of the backing set as desired per the decorator pattern.
 *
 *
Warning: The methods of {@code ForwardingNavigableSet} 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 ForwardingNavigableSet}.
 *
 *
Each of the {@code standard} methods uses the set's comparator (or the natural ordering of the
 * elements, if there is no comparator) to test element equality. As a result, if the comparator is
 * not consistent with equals, some of the standard implementations may violate the {@code Set}
 * contract.
 *
 *
The {@code standard} methods and the collection views they return are not guaranteed to be
 * thread-safe, even when all of the methods that they depend on are thread-safe.
 *
 * @author Louis Wasserman
 * @since 12.0
 */
@GwtIncompatible
public abstract class ForwardingNavigableSet<E> extends ForwardingSortedSet<E>
    implements NavigableSet<E> {

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

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

  @Override
  public E lower(E e) {
    return delegate().lower(e);
  }

  /**
   * A sensible definition of {@link #lower} in terms of the {@code descendingIterator} method of
   * {@link #headSet(Object, boolean)}. If you override {@link #headSet(Object, boolean)}, you may
   * wish to override {@link #lower} to forward to this implementation.
   */
  protected E standardLower(E e) {
    return Iterators.getNext(headSet(e, false).descendingIterator(), null);
  }

  @Override
  public E floor(E e) {
    return delegate().floor(e);
  }

  /**
   * A sensible definition of {@link #floor} in terms of the {@code descendingIterator} method of
   * {@link #headSet(Object, boolean)}. If you override {@link #headSet(Object, boolean)}, you may
   * wish to override {@link #floor} to forward to this implementation.
   */
  protected E standardFloor(E e) {
    return Iterators.getNext(headSet(e, true).descendingIterator(), null);
  }

  @Override
  public E ceiling(E e) {
    return delegate().ceiling(e);
  }

  /**
   * A sensible definition of {@link #ceiling} in terms of the {@code iterator} method of {@link
   * #tailSet(Object, boolean)}. If you override {@link #tailSet(Object, boolean)}, you may wish to
   * override {@link #ceiling} to forward to this implementation.
   */
  protected E standardCeiling(E e) {
    return Iterators.getNext(tailSet(e, true).iterator(), null);
  }

  @Override
  public E higher(E e) {
    return delegate().higher(e);
  }

  /**
   * A sensible definition of {@link #higher} in terms of the {@code iterator} method of {@link
   * #tailSet(Object, boolean)}. If you override {@link #tailSet(Object, boolean)}, you may wish to
   * override {@link #higher} to forward to this implementation.
   */
  protected E standardHigher(E e) {
    return Iterators.getNext(tailSet(e, false).iterator(), null);
  }

  @Override
  public E pollFirst() {
    return delegate().pollFirst();
  }

  /**
   * A sensible definition of {@link #pollFirst} in terms of the {@code iterator} method. If you
   * override {@link #iterator} you may wish to override {@link #pollFirst} to forward to this
   * implementation.
   */
  protected E standardPollFirst() {
    return Iterators.pollNext(iterator());
  }

  @Override
  public E pollLast() {
    return delegate().pollLast();
  }

  /**
   * A sensible definition of {@link #pollLast} in terms of the {@code descendingIterator} method.
   * If you override {@link #descendingIterator} you may wish to override {@link #pollLast} to
   * forward to this implementation.
   */
  protected E standardPollLast() {
    return Iterators.pollNext(descendingIterator());
  }

  protected E standardFirst() {
    return iterator().next();
  }

  protected E standardLast() {
    return descendingIterator().next();
  }

  @Override
  public NavigableSet<E> descendingSet() {
    return delegate().descendingSet();
  }

  /**
   * A sensible implementation of {@link NavigableSet#descendingSet} in terms of the other methods
   * of {@link NavigableSet}, notably including {@link NavigableSet#descendingIterator}.
   *
   *
In many cases, you may wish to override {@link ForwardingNavigableSet#descendingSet} to
   * forward to this implementation or a subclass thereof.
   *
   * @since 12.0
   */
  @Beta
  protected class StandardDescendingSet extends Sets.DescendingSet<E> {
    /** Constructor for use by subclasses. */
    public StandardDescendingSet() {
      super(ForwardingNavigableSet.this);
    }
  }

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

  @Override
  public NavigableSet<E> subSet(
      E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
    return delegate().subSet(fromElement, fromInclusive, toElement, toInclusive);
  }

  /**
   * A sensible definition of {@link #subSet(Object, boolean, Object, boolean)} in terms of the
   * {@code headSet} and {@code tailSet} methods. In many cases, you may wish to override {@link
   * #subSet(Object, boolean, Object, boolean)} to forward to this implementation.
   */
  @Beta
  protected NavigableSet<E> standardSubSet(
      E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
    return tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive);
  }

  /**
   * A sensible definition of {@link #subSet(Object, Object)} in terms of the {@link #subSet(Object,
   * boolean, Object, boolean)} method. If you override {@link #subSet(Object, boolean, Object,
   * boolean)}, you may wish to override {@link #subSet(Object, Object)} to forward to this
   * implementation.
   */
  @Override
  protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
    return subSet(fromElement, true, toElement, false);
  }

  @Override
  public NavigableSet<E> headSet(E toElement, boolean inclusive) {
    return delegate().headSet(toElement, inclusive);
  }

  /**
   * A sensible definition of {@link #headSet(Object)} in terms of the {@link #headSet(Object,
   * boolean)} method. If you override {@link #headSet(Object, boolean)}, you may wish to override
   * {@link #headSet(Object)} to forward to this implementation.
   */
  protected SortedSet<E> standardHeadSet(E toElement) {
    return headSet(toElement, false);
  }

  @Override
  public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
    return delegate().tailSet(fromElement, inclusive);
  }

  /**
   * A sensible definition of {@link #tailSet(Object)} in terms of the {@link #tailSet(Object,
   * boolean)} method. If you override {@link #tailSet(Object, boolean)}, you may wish to override
   * {@link #tailSet(Object)} to forward to this implementation.
   */
  protected SortedSet<E> standardTailSet(E fromElement) {
    return tailSet(fromElement, true);
  }
}