1 /*
2  * Copyright 2017-2020 the original author or 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  *      https://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 package org.springframework.data.util;
17
18 import lombok.AccessLevel;
19 import lombok.NonNull;
20 import lombok.RequiredArgsConstructor;
21
22 import java.util.EnumSet;
23 import java.util.HashMap;
24 import java.util.Set;
25 import java.util.function.BiConsumer;
26 import java.util.function.BinaryOperator;
27 import java.util.function.Function;
28 import java.util.function.Supplier;
29 import java.util.stream.Collector;
30
31 import org.springframework.util.CollectionUtils;
32 import org.springframework.util.MultiValueMap;
33
34 /**
35  * A {@link Collector} for building a {@link MultiValueMap} from a {@link java.util.stream.Stream}.
36  *
37  * @author Jens Schauder
38  * @since 2.0
39  */

40 @RequiredArgsConstructor(access = AccessLevel.PACKAGE, staticName = "of")
41 class MultiValueMapCollector<T, K, V> implements Collector<T, MultiValueMap<K, V>, MultiValueMap<K, V>> {
42
43     private final @NonNull Function<T, K> keyFunction;
44     private final @NonNull Function<T, V> valueFunction;
45
46     /*
47      * (non-Javadoc)
48      * @see java.util.stream.Collector#supplier()
49      */

50     @Override
51     public Supplier<MultiValueMap<K, V>> supplier() {
52         return () -> CollectionUtils.toMultiValueMap(new HashMap<>());
53     }
54
55     /*
56      * (non-Javadoc)
57      * @see java.util.stream.Collector#accumulator()
58      */

59     @Override
60     public BiConsumer<MultiValueMap<K, V>, T> accumulator() {
61         return (map, t) -> map.add(keyFunction.apply(t), valueFunction.apply(t));
62     }
63
64     /*
65      * (non-Javadoc)
66      * @see java.util.stream.Collector#combiner()
67      */

68     @Override
69     public BinaryOperator<MultiValueMap<K, V>> combiner() {
70
71         return (map1, map2) -> {
72
73             for (K key : map2.keySet()) {
74                 map1.addAll(key, map2.get(key));
75             }
76
77             return map1;
78         };
79     }
80
81     /*
82      * (non-Javadoc)
83      * @see java.util.stream.Collector#finisher()
84      */

85     @Override
86     public Function<MultiValueMap<K, V>, MultiValueMap<K, V>> finisher() {
87         return Function.identity();
88     }
89
90     /*
91      * (non-Javadoc)
92      * @see java.util.stream.Collector#characteristics()
93      */

94     @Override
95     public Set<Characteristics> characteristics() {
96         return EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.UNORDERED);
97     }
98 }
99