/*
* 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 org.jdbi.v3.core.collector;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collector;
Provides Collectors for built in JDK container types.
Supported container types:
- java.util.Optional<T> (throws an exception if more than one row in result)
- java.util.Collection<T>
- java.util.List<T>
- java.util.ArrayList<T>
- java.util.LinkedList<T>
- java.util.concurrent.CopyOnWriteArrayList<T>
- java.util.Set<T>
- java.util.HashSet<T>
- java.util.LinkedHashSet<T>
- java.util.SortedSet<T>
- java.util.TreeSet<T>
Supported Map types - for rows mapped to Map.Entry<K, V>
- java.util.Map<K, V>
- java.util.HashMap<K, V>
- java.util.LinkedHashMap<K, V>
- java.util.SortedMap<K, V>
- java.util.TreeMap<K, V>
- java.util.concurrent.ConcurrentMap<K, V>
- java.util.concurrent.ConcurrentHashMap<K, V>
- java.util.WeakHashMap<K, V>
Deprecated: will be replaced by plugin
/**
* Provides Collectors for built in JDK container types.
* <p>Supported container types:</p>
* <ul>
* <li>java.util.Optional<T> (throws an exception if more than one row in result)</li>
* <li>java.util.Collection<T></li>
* <li>java.util.List<T></li>
* <li>java.util.ArrayList<T></li>
* <li>java.util.LinkedList<T></li>
* <li>java.util.concurrent.CopyOnWriteArrayList<T></li>
* <li>java.util.Set<T></li>
* <li>java.util.HashSet<T></li>
* <li>java.util.LinkedHashSet<T></li>
* <li>java.util.SortedSet<T></li>
* <li>java.util.TreeSet<T></li>
* </ul>
* <p>Supported Map types - for rows mapped to Map.Entry<K, V></p>
* <ul>
* <li>java.util.Map<K, V></li>
* <li>java.util.HashMap<K, V></li>
* <li>java.util.LinkedHashMap<K, V></li>
* <li>java.util.SortedMap<K, V></li>
* <li>java.util.TreeMap<K, V></li>
* <li>java.util.concurrent.ConcurrentMap<K, V></li>
* <li>java.util.concurrent.ConcurrentHashMap<K, V></li>
* <li>java.util.WeakHashMap<K, V></li>
* </ul>
*
* @deprecated will be replaced by plugin
*/
@Deprecated
public class BuiltInCollectorFactory implements CollectorFactory {
private static final List<CollectorFactory> FACTORIES = Arrays.asList(
new MapCollectorFactory(),
new OptionalCollectorFactory(),
new ListCollectorFactory(),
new SetCollectorFactory()
);
@Override
public boolean accepts(Type containerType) {
return FACTORIES.stream().anyMatch(factory -> factory.accepts(containerType));
}
@Override
public Optional<Type> elementType(Type containerType) {
return FACTORIES.stream()
.map(factory -> factory.elementType(containerType))
.filter(Optional::isPresent)
.findFirst()
.map(Optional::get);
}
@Override
public Collector<?, ?, ?> build(Type containerType) {
return FACTORIES.stream()
.filter(factory -> factory.accepts(containerType))
.map(factory -> factory.build(containerType))
.findFirst()
.orElseThrow(() -> new RuntimeException("Unprovidable collector was requested. This is an internal jdbi bug; please report it to the jdbi developers."));
}
Returns a Collector
that accumulates 0 or 1 input elements into an Optional<T>
. The returned collector will throw IllegalStateException
whenever 2 or more elements are present in a stream. Type parameters: - <T> – the collected type
Returns: a Collector
which collects 0 or 1 input elements into an Optional<T>
. Deprecated: Use OptionalCollectors.toOptional()
instead.
/**
* Returns a {@code Collector} that accumulates 0 or 1 input elements into an {@code Optional<T>}.
* The returned collector will throw {@code IllegalStateException} whenever 2 or more elements
* are present in a stream.
*
* @param <T> the collected type
* @return a {@code Collector} which collects 0 or 1 input elements into an {@code Optional<T>}.
* @deprecated Use {@link OptionalCollectors#toOptional()} instead.
*/
@Deprecated
public static <T> Collector<T, ?, Optional<T>> toOptional() {
return OptionalCollectors.toOptional();
}
Returns a Collector
that accumulates Map.Entry<K, V>
input elements into a map of the supplied type. The returned collector will throw IllegalStateException
whenever a set of input elements contains multiple entries with the same key. Params: - mapFactory – a
Supplier
which returns a new, empty Map
of the appropriate type.
Type parameters: Returns: a Collector
which collects map entry elements into a Map
, in encounter order. Deprecated: Use MapCollectors.toMap(Supplier<Map<Object,Object>>)
instead.
/**
* Returns a {@code Collector} that accumulates {@code Map.Entry<K, V>} input elements into a
* map of the supplied type. The returned collector will throw {@code IllegalStateException}
* whenever a set of input elements contains multiple entries with the same key.
*
* @param <K> the type of map keys
* @param <V> the type of map values
* @param <M> the type of the resulting {@code Map}
* @param mapFactory a {@code Supplier} which returns a new, empty {@code Map} of the appropriate type.
* @return a {@code Collector} which collects map entry elements into a {@code Map}, in encounter order.
*
* @deprecated Use {@link MapCollectors#toMap(Supplier)} instead.
*/
@Deprecated
public static <K, V, M extends Map<K, V>> Collector<Map.Entry<K, V>, ?, M> toMap(Supplier<M> mapFactory) {
return Collector.of(
mapFactory,
BuiltInCollectorFactory::putEntry,
BuiltInCollectorFactory::combine);
}
private static <K, V, M extends Map<K, V>> void putEntry(M map, Map.Entry<K, V> entry) {
putEntry(map, entry.getKey(), entry.getValue());
}
private static <K, V, M extends Map<K, V>> void putEntry(M map, K key, V value) {
V oldValue = map.put(key, value);
if (oldValue != null) {
throw new IllegalStateException(String.format(
"Multiple values for Map key '%s': ['%s','%s',...]",
key,
oldValue,
value));
}
}
private static <K, V, M extends Map<K, V>> M combine(M a, M b) {
b.forEach((k, v) -> putEntry(a, k, v));
return a;
}
}