1 /*
2  * Copyright (C) 2013 The Dagger 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 dagger.internal.codegen.extension;
18 
19 import static java.util.stream.Collectors.collectingAndThen;
20 import static java.util.stream.Collectors.toList;
21 
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableMap;
24 import com.google.common.collect.ImmutableSet;
25 import com.google.common.collect.ImmutableSetMultimap;
26 import com.google.common.collect.Maps;
27 import java.util.Collection;
28 import java.util.EnumSet;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.function.Function;
32 import java.util.stream.Collector;
33 import java.util.stream.Collectors;
34 import java.util.stream.Stream;
35 import java.util.stream.StreamSupport;
36 
37 /** Utilities for streams. */
38 public final class DaggerStreams {
39 
40   /**
41    * Returns a {@link Collector} that accumulates the input elements into a new {@link
42    * ImmutableList}, in encounter order.
43    */
44   // TODO(b/68008628): Use ImmutableList.toImmutableList().
toImmutableList()45   public static <T> Collector<T, ?, ImmutableList<T>> toImmutableList() {
46     return collectingAndThen(toList(), ImmutableList::copyOf);
47   }
48 
49   /**
50    * Returns a {@link Collector} that accumulates the input elements into a new {@link
51    * ImmutableSet}, in encounter order.
52    */
53   // TODO(b/68008628): Use ImmutableSet.toImmutableSet().
toImmutableSet()54   public static <T> Collector<T, ?, ImmutableSet<T>> toImmutableSet() {
55     return collectingAndThen(toList(), ImmutableSet::copyOf);
56   }
57 
58   /**
59    * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys
60    * and values are the result of applying the provided mapping functions to the input elements.
61    * Entries appear in the result {@code ImmutableMap} in encounter order.
62    */
63   // TODO(b/68008628): Use ImmutableMap.toImmutableMap().
toImmutableMap( Function<? super T, K> keyMapper, Function<? super T, V> valueMapper)64   public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
65       Function<? super T, K> keyMapper, Function<? super T, V> valueMapper) {
66     return Collectors.mapping(
67         value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
68         Collector.of(
69             ImmutableMap::builder,
70             (ImmutableMap.Builder<K, V> builder, Map.Entry<K, V> entry) -> builder.put(entry),
71             (left, right) -> left.putAll(right.build()),
72             ImmutableMap.Builder::build));
73   }
74 
75   /**
76    * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSetMultimap}
77    * whose keys and values are the result of applying the provided mapping functions to the input
78    * elements. Entries appear in the result {@code ImmutableSetMultimap} in encounter order.
79    */
80   // TODO(b/68008628): Use ImmutableSetMultimap.toImmutableSetMultimap().
toImmutableSetMultimap( Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper)81   public static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> toImmutableSetMultimap(
82       Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) {
83     return Collectors.mapping(
84         value -> Maps.immutableEntry(keyMapper.apply(value), valueMapper.apply(value)),
85         Collector.of(
86             ImmutableSetMultimap::builder,
87             (ImmutableSetMultimap.Builder<K, V> builder, Map.Entry<K, V> entry) ->
88                 builder.put(entry),
89             (left, right) -> left.putAll(right.build()),
90             ImmutableSetMultimap.Builder::build));
91   }
92 
93   /**
94    * Returns a function from {@link Object} to {@code Stream<T>}, which returns a stream containing
95    * its input if its input is an instance of {@code T}.
96    *
97    * <p>Use as an argument to {@link Stream#flatMap(Function)}:
98    *
99    * <pre>{@code Stream<Bar>} barStream = fooStream.flatMap(instancesOf(Bar.class));</pre>
100    */
instancesOf(Class<T> to)101   public static <T> Function<Object, Stream<T>> instancesOf(Class<T> to) {
102     return f -> to.isInstance(f) ? Stream.of(to.cast(f)) : Stream.empty();
103   }
104 
105   /** Returns a stream of all values of the given {@code enumType}. */
valuesOf(Class<E> enumType)106   public static <E extends Enum<E>> Stream<E> valuesOf(Class<E> enumType) {
107     return EnumSet.allOf(enumType).stream();
108   }
109 
110   /**
111    * A function that you can use to extract the present values from a stream of {@link Optional}s.
112    *
113    * <pre>{@code
114    * Set<Foo> foos =
115    *     optionalFoos()
116    *         .flatMap(DaggerStreams.presentValues())
117    *         .collect(toSet());
118    * }</pre>
119    */
presentValues()120   public static <T> Function<Optional<T>, Stream<T>> presentValues() {
121     return optional -> optional.map(Stream::of).orElse(Stream.empty());
122   }
123 
124   /**
125    * Returns a sequential {@link Stream} of the contents of {@code iterable}, delegating to {@link
126    * Collection#stream} if possible.
127    */
stream(Iterable<T> iterable)128   public static <T> Stream<T> stream(Iterable<T> iterable) {
129     return (iterable instanceof Collection)
130         ? ((Collection<T>) iterable).stream()
131         : StreamSupport.stream(iterable.spliterator(), false);
132   }
133 
DaggerStreams()134   private DaggerStreams() {}
135 }
136