1 /*
2  * Copyright (C) 2017 The Android Open Source Project
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 android.inputmethodservice.cts.devicetest;
18 
19 import java.util.function.BiConsumer;
20 import java.util.function.Predicate;
21 import java.util.stream.Collector;
22 import java.util.stream.Stream;
23 import java.util.stream.Stream.Builder;
24 
25 /**
26  * More stream collectors.
27  */
28 final class MoreCollectors {
29 
30     /**
31      * Create a collector that collects elements ending at an element that satisfies specified
32      * predicate. For example,
33      * <pre>
34      * Stream.of("a", "b", "c", "d", "c", "d", "e").collect(endingAt(s -> s.equals("d")))
35      * </pre>
36      * returns {@code Stream.of("a", "b", "c", "d")}.
37      *
38      * @param predicate a predicator to find a specific element.
39      * @param <E> a type of element.
40      * @return {@link Collector} object that collects elements ending at an element that is
41      *          accepted by {@code predicate}.
42      */
endingAt(Predicate<E> predicate)43     static <E> Collector<E, ?, Stream<E>> endingAt(Predicate<E> predicate) {
44         final BiConsumer<Builder<E>, E> endingAtAccumulator = new BiConsumer<Builder<E>, E>() {
45             private boolean mFound = false;
46 
47             @Override
48             public void accept(Builder<E> builder, E element) {
49                 if (mFound) {
50                     return;
51                 }
52                 if (predicate.test(element)) {
53                     mFound = true;
54                 }
55                 builder.accept(element);
56             }
57         };
58         return Collector.of(
59                 Stream::builder,
60                 endingAtAccumulator,
61                 (builder, builder2) -> {
62                     throw new UnsupportedOperationException("Do not use on parallel stream.");
63                 },
64                 Builder::build);
65     }
66 
67     /**
68      * Create a collector that collects elements starting from an element that satisfies specified
69      * predicate. For example,
70      * <pre>
71      * Stream.of("a", "b", "c", "d", "c", "d", "e").collect(startingFrom(s -> s.equals("d")))
72      * </pre>
73      * returns {@code Stream.of("d", "c", "d", "e")}.
74      *
75      * @param predicate a predicator to find a specific element.
76      * @param <E> a type of element.
77      * @return {@link Collector} object that collects elements starting from an element that is
78      *          accepted by {@code predicate}.
79      */
startingFrom(Predicate<E> predicate)80     static <E> Collector<E, ?, Stream<E>> startingFrom(Predicate<E> predicate) {
81         final BiConsumer<Builder<E>, E> startingFromAccumulator = new BiConsumer<Builder<E>, E>() {
82             private boolean mFound = false;
83 
84             @Override
85             public void accept(Builder<E> builder, E element) {
86                 if (mFound) {
87                     builder.accept(element);
88                     return;
89                 }
90                 if (predicate.test(element)) {
91                     mFound = true;
92                     builder.accept(element);
93                 }
94             }
95         };
96         return Collector.of(
97                 Stream::builder,
98                 startingFromAccumulator,
99                 (builder, builder2) -> {
100                     throw new UnsupportedOperationException("Do not use on parallel stream.");
101                 },
102                 Builder::build);
103     }
104 }
105