diff --git a/android/guava/src/com/google/common/collect/IgnoreJRERequirement.java b/android/guava/src/com/google/common/collect/IgnoreJRERequirement.java new file mode 100644 index 000000000000..2a1006831267 --- /dev/null +++ b/android/guava/src/com/google/common/collect/IgnoreJRERequirement.java @@ -0,0 +1,30 @@ +/* + * Copyright 2019 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 java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Target; + +/** + * Disables Animal Sniffer's checking of compatibility with older versions of Java/Android. + * + *

Each package's copy of this annotation needs to be listed in our {@code pom.xml}. + */ +@Target({METHOD, CONSTRUCTOR, TYPE}) +@ElementTypesAreNonnullByDefault +@interface IgnoreJRERequirement {} diff --git a/android/guava/src/com/google/common/collect/TableCollectors.java b/android/guava/src/com/google/common/collect/TableCollectors.java new file mode 100644 index 000000000000..9e71d80abd87 --- /dev/null +++ b/android/guava/src/com/google/common/collect/TableCollectors.java @@ -0,0 +1,225 @@ +/* + * 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.checkNotNull; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.Tables.AbstractCell; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** Collectors utilities for {@code common.collect.Table} internals. */ +@GwtCompatible +@ElementTypesAreNonnullByDefault +@SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"}) +@IgnoreJRERequirement // used only from APIs with Java 8 types in them +// (not used publicly by guava-android as of this writing, but we include it in the jar as a test) +final class TableCollectors { + + static + Collector> toImmutableTable( + Function rowFunction, + Function columnFunction, + Function valueFunction) { + checkNotNull(rowFunction, "rowFunction"); + checkNotNull(columnFunction, "columnFunction"); + checkNotNull(valueFunction, "valueFunction"); + return Collector.of( + (Supplier>) ImmutableTable.Builder::new, + (builder, t) -> + builder.put(rowFunction.apply(t), columnFunction.apply(t), valueFunction.apply(t)), + ImmutableTable.Builder::combine, + ImmutableTable.Builder::build); + } + + static + Collector> toImmutableTable( + Function rowFunction, + Function columnFunction, + Function valueFunction, + BinaryOperator mergeFunction) { + + checkNotNull(rowFunction, "rowFunction"); + checkNotNull(columnFunction, "columnFunction"); + checkNotNull(valueFunction, "valueFunction"); + checkNotNull(mergeFunction, "mergeFunction"); + + /* + * No mutable Table exactly matches the insertion order behavior of ImmutableTable.Builder, but + * the Builder can't efficiently support merging of duplicate values. Getting around this + * requires some work. + */ + + return Collector.of( + ImmutableTableCollectorState::new, + (state, input) -> + state.put( + rowFunction.apply(input), + columnFunction.apply(input), + valueFunction.apply(input), + mergeFunction), + (s1, s2) -> s1.combine(s2, mergeFunction), + state -> state.toTable()); + } + + static < + T extends @Nullable Object, + R extends @Nullable Object, + C extends @Nullable Object, + V extends @Nullable Object, + I extends Table> + Collector toTable( + java.util.function.Function rowFunction, + java.util.function.Function columnFunction, + java.util.function.Function valueFunction, + java.util.function.Supplier tableSupplier) { + return toTable( + rowFunction, + columnFunction, + valueFunction, + (v1, v2) -> { + throw new IllegalStateException("Conflicting values " + v1 + " and " + v2); + }, + tableSupplier); + } + + static < + T extends @Nullable Object, + R extends @Nullable Object, + C extends @Nullable Object, + V extends @Nullable Object, + I extends Table> + Collector toTable( + java.util.function.Function rowFunction, + java.util.function.Function columnFunction, + java.util.function.Function valueFunction, + BinaryOperator mergeFunction, + java.util.function.Supplier tableSupplier) { + checkNotNull(rowFunction); + checkNotNull(columnFunction); + checkNotNull(valueFunction); + checkNotNull(mergeFunction); + checkNotNull(tableSupplier); + return Collector.of( + tableSupplier, + (table, input) -> + mergeTables( + table, + rowFunction.apply(input), + columnFunction.apply(input), + valueFunction.apply(input), + mergeFunction), + (table1, table2) -> { + for (Table.Cell cell2 : table2.cellSet()) { + mergeTables( + table1, cell2.getRowKey(), cell2.getColumnKey(), cell2.getValue(), mergeFunction); + } + return table1; + }); + } + + private static final class ImmutableTableCollectorState { + final List> insertionOrder = new ArrayList<>(); + final Table> table = HashBasedTable.create(); + + void put(R row, C column, V value, BinaryOperator merger) { + MutableCell oldCell = table.get(row, column); + if (oldCell == null) { + MutableCell cell = new MutableCell<>(row, column, value); + insertionOrder.add(cell); + table.put(row, column, cell); + } else { + oldCell.merge(value, merger); + } + } + + ImmutableTableCollectorState combine( + ImmutableTableCollectorState other, BinaryOperator merger) { + for (MutableCell cell : other.insertionOrder) { + put(cell.getRowKey(), cell.getColumnKey(), cell.getValue(), merger); + } + return this; + } + + ImmutableTable toTable() { + return ImmutableTable.copyOf(insertionOrder); + } + } + + @IgnoreJRERequirement // see enclosing class (whose annotation Animal Sniffer ignores here...) + private static final class MutableCell extends AbstractCell { + private final R row; + private final C column; + private V value; + + MutableCell(R row, C column, V value) { + this.row = checkNotNull(row, "row"); + this.column = checkNotNull(column, "column"); + this.value = checkNotNull(value, "value"); + } + + @Override + public R getRowKey() { + return row; + } + + @Override + public C getColumnKey() { + return column; + } + + @Override + public V getValue() { + return value; + } + + void merge(V value, BinaryOperator mergeFunction) { + checkNotNull(value, "value"); + this.value = checkNotNull(mergeFunction.apply(this.value, value), "mergeFunction.apply"); + } + } + + private static < + R extends @Nullable Object, C extends @Nullable Object, V extends @Nullable Object> + void mergeTables( + Table table, + @ParametricNullness R row, + @ParametricNullness C column, + @ParametricNullness V value, + BinaryOperator mergeFunction) { + checkNotNull(value); + V oldValue = table.get(row, column); + if (oldValue == null) { + table.put(row, column, value); + } else { + V newValue = mergeFunction.apply(oldValue, value); + if (newValue == null) { + table.remove(row, column); + } else { + table.put(row, column, newValue); + } + } + } + + private TableCollectors() {} +} diff --git a/android/pom.xml b/android/pom.xml index c57f5846c067..2ee9ed9d21bb 100644 --- a/android/pom.xml +++ b/android/pom.xml @@ -176,7 +176,7 @@ animal-sniffer-maven-plugin 1.23 - com.google.common.hash.IgnoreJRERequirement,com.google.common.io.IgnoreJRERequirement,com.google.common.reflect.IgnoreJRERequirement,com.google.common.testing.IgnoreJRERequirement + com.google.common.collect.IgnoreJRERequirement,com.google.common.hash.IgnoreJRERequirement,com.google.common.io.IgnoreJRERequirement,com.google.common.reflect.IgnoreJRERequirement,com.google.common.testing.IgnoreJRERequirement true org.codehaus.mojo.signature diff --git a/guava/src/com/google/common/collect/IgnoreJRERequirement.java b/guava/src/com/google/common/collect/IgnoreJRERequirement.java new file mode 100644 index 000000000000..2a1006831267 --- /dev/null +++ b/guava/src/com/google/common/collect/IgnoreJRERequirement.java @@ -0,0 +1,30 @@ +/* + * Copyright 2019 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 java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +import java.lang.annotation.Target; + +/** + * Disables Animal Sniffer's checking of compatibility with older versions of Java/Android. + * + *

Each package's copy of this annotation needs to be listed in our {@code pom.xml}. + */ +@Target({METHOD, CONSTRUCTOR, TYPE}) +@ElementTypesAreNonnullByDefault +@interface IgnoreJRERequirement {} diff --git a/pom.xml b/pom.xml index 5ee5d050f768..6491e13d9686 100644 --- a/pom.xml +++ b/pom.xml @@ -177,7 +177,7 @@ animal-sniffer-maven-plugin 1.23 - com.google.common.hash.IgnoreJRERequirement,com.google.common.io.IgnoreJRERequirement,com.google.common.reflect.IgnoreJRERequirement,com.google.common.testing.IgnoreJRERequirement + com.google.common.collect.IgnoreJRERequirement,com.google.common.hash.IgnoreJRERequirement,com.google.common.io.IgnoreJRERequirement,com.google.common.reflect.IgnoreJRERequirement,com.google.common.testing.IgnoreJRERequirement true org.codehaus.mojo.signature