Skip to content

Commit 39c45d2

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Prepare to make ImmutableTable.toImmutableTable available in guava-android (but don't do so yet).
Progress toward #6567 RELNOTES=n/a PiperOrigin-RevId: 543468006
1 parent 2c983f9 commit 39c45d2

File tree

5 files changed

+287
-2
lines changed

5 files changed

+287
-2
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2019 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.common.collect;
16+
17+
import static java.lang.annotation.ElementType.CONSTRUCTOR;
18+
import static java.lang.annotation.ElementType.METHOD;
19+
import static java.lang.annotation.ElementType.TYPE;
20+
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* Disables Animal Sniffer's checking of compatibility with older versions of Java/Android.
25+
*
26+
* <p>Each package's copy of this annotation needs to be listed in our {@code pom.xml}.
27+
*/
28+
@Target({METHOD, CONSTRUCTOR, TYPE})
29+
@ElementTypesAreNonnullByDefault
30+
@interface IgnoreJRERequirement {}
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* Copyright (C) 2009 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.common.collect;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
21+
import com.google.common.annotations.GwtCompatible;
22+
import com.google.common.collect.Tables.AbstractCell;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.function.BinaryOperator;
26+
import java.util.function.Function;
27+
import java.util.function.Supplier;
28+
import java.util.stream.Collector;
29+
import org.checkerframework.checker.nullness.qual.Nullable;
30+
31+
/** Collectors utilities for {@code common.collect.Table} internals. */
32+
@GwtCompatible
33+
@ElementTypesAreNonnullByDefault
34+
@SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
35+
@IgnoreJRERequirement // used only from APIs with Java 8 types in them
36+
// (not used publicly by guava-android as of this writing, but we include it in the jar as a test)
37+
final class TableCollectors {
38+
39+
static <T extends @Nullable Object, R, C, V>
40+
Collector<T, ?, ImmutableTable<R, C, V>> toImmutableTable(
41+
Function<? super T, ? extends R> rowFunction,
42+
Function<? super T, ? extends C> columnFunction,
43+
Function<? super T, ? extends V> valueFunction) {
44+
checkNotNull(rowFunction, "rowFunction");
45+
checkNotNull(columnFunction, "columnFunction");
46+
checkNotNull(valueFunction, "valueFunction");
47+
return Collector.of(
48+
(Supplier<ImmutableTable.Builder<R, C, V>>) ImmutableTable.Builder::new,
49+
(builder, t) ->
50+
builder.put(rowFunction.apply(t), columnFunction.apply(t), valueFunction.apply(t)),
51+
ImmutableTable.Builder::combine,
52+
ImmutableTable.Builder::build);
53+
}
54+
55+
static <T extends @Nullable Object, R, C, V>
56+
Collector<T, ?, ImmutableTable<R, C, V>> toImmutableTable(
57+
Function<? super T, ? extends R> rowFunction,
58+
Function<? super T, ? extends C> columnFunction,
59+
Function<? super T, ? extends V> valueFunction,
60+
BinaryOperator<V> mergeFunction) {
61+
62+
checkNotNull(rowFunction, "rowFunction");
63+
checkNotNull(columnFunction, "columnFunction");
64+
checkNotNull(valueFunction, "valueFunction");
65+
checkNotNull(mergeFunction, "mergeFunction");
66+
67+
/*
68+
* No mutable Table exactly matches the insertion order behavior of ImmutableTable.Builder, but
69+
* the Builder can't efficiently support merging of duplicate values. Getting around this
70+
* requires some work.
71+
*/
72+
73+
return Collector.of(
74+
ImmutableTableCollectorState<R, C, V>::new,
75+
(state, input) ->
76+
state.put(
77+
rowFunction.apply(input),
78+
columnFunction.apply(input),
79+
valueFunction.apply(input),
80+
mergeFunction),
81+
(s1, s2) -> s1.combine(s2, mergeFunction),
82+
state -> state.toTable());
83+
}
84+
85+
static <
86+
T extends @Nullable Object,
87+
R extends @Nullable Object,
88+
C extends @Nullable Object,
89+
V extends @Nullable Object,
90+
I extends Table<R, C, V>>
91+
Collector<T, ?, I> toTable(
92+
java.util.function.Function<? super T, ? extends R> rowFunction,
93+
java.util.function.Function<? super T, ? extends C> columnFunction,
94+
java.util.function.Function<? super T, ? extends V> valueFunction,
95+
java.util.function.Supplier<I> tableSupplier) {
96+
return toTable(
97+
rowFunction,
98+
columnFunction,
99+
valueFunction,
100+
(v1, v2) -> {
101+
throw new IllegalStateException("Conflicting values " + v1 + " and " + v2);
102+
},
103+
tableSupplier);
104+
}
105+
106+
static <
107+
T extends @Nullable Object,
108+
R extends @Nullable Object,
109+
C extends @Nullable Object,
110+
V extends @Nullable Object,
111+
I extends Table<R, C, V>>
112+
Collector<T, ?, I> toTable(
113+
java.util.function.Function<? super T, ? extends R> rowFunction,
114+
java.util.function.Function<? super T, ? extends C> columnFunction,
115+
java.util.function.Function<? super T, ? extends V> valueFunction,
116+
BinaryOperator<V> mergeFunction,
117+
java.util.function.Supplier<I> tableSupplier) {
118+
checkNotNull(rowFunction);
119+
checkNotNull(columnFunction);
120+
checkNotNull(valueFunction);
121+
checkNotNull(mergeFunction);
122+
checkNotNull(tableSupplier);
123+
return Collector.of(
124+
tableSupplier,
125+
(table, input) ->
126+
mergeTables(
127+
table,
128+
rowFunction.apply(input),
129+
columnFunction.apply(input),
130+
valueFunction.apply(input),
131+
mergeFunction),
132+
(table1, table2) -> {
133+
for (Table.Cell<R, C, V> cell2 : table2.cellSet()) {
134+
mergeTables(
135+
table1, cell2.getRowKey(), cell2.getColumnKey(), cell2.getValue(), mergeFunction);
136+
}
137+
return table1;
138+
});
139+
}
140+
141+
private static final class ImmutableTableCollectorState<R, C, V> {
142+
final List<MutableCell<R, C, V>> insertionOrder = new ArrayList<>();
143+
final Table<R, C, MutableCell<R, C, V>> table = HashBasedTable.create();
144+
145+
void put(R row, C column, V value, BinaryOperator<V> merger) {
146+
MutableCell<R, C, V> oldCell = table.get(row, column);
147+
if (oldCell == null) {
148+
MutableCell<R, C, V> cell = new MutableCell<>(row, column, value);
149+
insertionOrder.add(cell);
150+
table.put(row, column, cell);
151+
} else {
152+
oldCell.merge(value, merger);
153+
}
154+
}
155+
156+
ImmutableTableCollectorState<R, C, V> combine(
157+
ImmutableTableCollectorState<R, C, V> other, BinaryOperator<V> merger) {
158+
for (MutableCell<R, C, V> cell : other.insertionOrder) {
159+
put(cell.getRowKey(), cell.getColumnKey(), cell.getValue(), merger);
160+
}
161+
return this;
162+
}
163+
164+
ImmutableTable<R, C, V> toTable() {
165+
return ImmutableTable.copyOf(insertionOrder);
166+
}
167+
}
168+
169+
@IgnoreJRERequirement // see enclosing class (whose annotation Animal Sniffer ignores here...)
170+
private static final class MutableCell<R, C, V> extends AbstractCell<R, C, V> {
171+
private final R row;
172+
private final C column;
173+
private V value;
174+
175+
MutableCell(R row, C column, V value) {
176+
this.row = checkNotNull(row, "row");
177+
this.column = checkNotNull(column, "column");
178+
this.value = checkNotNull(value, "value");
179+
}
180+
181+
@Override
182+
public R getRowKey() {
183+
return row;
184+
}
185+
186+
@Override
187+
public C getColumnKey() {
188+
return column;
189+
}
190+
191+
@Override
192+
public V getValue() {
193+
return value;
194+
}
195+
196+
void merge(V value, BinaryOperator<V> mergeFunction) {
197+
checkNotNull(value, "value");
198+
this.value = checkNotNull(mergeFunction.apply(this.value, value), "mergeFunction.apply");
199+
}
200+
}
201+
202+
private static <
203+
R extends @Nullable Object, C extends @Nullable Object, V extends @Nullable Object>
204+
void mergeTables(
205+
Table<R, C, V> table,
206+
@ParametricNullness R row,
207+
@ParametricNullness C column,
208+
@ParametricNullness V value,
209+
BinaryOperator<V> mergeFunction) {
210+
checkNotNull(value);
211+
V oldValue = table.get(row, column);
212+
if (oldValue == null) {
213+
table.put(row, column, value);
214+
} else {
215+
V newValue = mergeFunction.apply(oldValue, value);
216+
if (newValue == null) {
217+
table.remove(row, column);
218+
} else {
219+
table.put(row, column, newValue);
220+
}
221+
}
222+
}
223+
224+
private TableCollectors() {}
225+
}

android/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@
176176
<artifactId>animal-sniffer-maven-plugin</artifactId>
177177
<version>1.23</version>
178178
<configuration>
179-
<annotations>com.google.common.hash.IgnoreJRERequirement,com.google.common.io.IgnoreJRERequirement,com.google.common.reflect.IgnoreJRERequirement,com.google.common.testing.IgnoreJRERequirement</annotations>
179+
<annotations>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</annotations>
180180
<checkTestClasses>true</checkTestClasses>
181181
<signature>
182182
<groupId>org.codehaus.mojo.signature</groupId>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2019 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package com.google.common.collect;
16+
17+
import static java.lang.annotation.ElementType.CONSTRUCTOR;
18+
import static java.lang.annotation.ElementType.METHOD;
19+
import static java.lang.annotation.ElementType.TYPE;
20+
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* Disables Animal Sniffer's checking of compatibility with older versions of Java/Android.
25+
*
26+
* <p>Each package's copy of this annotation needs to be listed in our {@code pom.xml}.
27+
*/
28+
@Target({METHOD, CONSTRUCTOR, TYPE})
29+
@ElementTypesAreNonnullByDefault
30+
@interface IgnoreJRERequirement {}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@
177177
<artifactId>animal-sniffer-maven-plugin</artifactId>
178178
<version>1.23</version>
179179
<configuration>
180-
<annotations>com.google.common.hash.IgnoreJRERequirement,com.google.common.io.IgnoreJRERequirement,com.google.common.reflect.IgnoreJRERequirement,com.google.common.testing.IgnoreJRERequirement</annotations>
180+
<annotations>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</annotations>
181181
<checkTestClasses>true</checkTestClasses>
182182
<signature>
183183
<groupId>org.codehaus.mojo.signature</groupId>

0 commit comments

Comments
 (0)