public JdbiCollectors() { // TODO move to BuiltInSupportPlugin register(new MapCollectorFactory()); register(new OptionalCollectorFactory()); register(new ListCollectorFactory()); register(new SetCollectorFactory()); register(new OptionalPrimitiveCollectorFactory()); register(new ArrayCollectorFactory()); register(new EnumSetCollectorFactory()); }
/** * Returns a {@code Collector} that accumulates 0 or 1 input {@code Long} elements into an * {@code OptionalLong}. The returned collector will throw {@code IllegalStateException} whenever * 2 or more elements are present in a stream. Null elements are mapped to * {@code OptionalLong.empty()}. * * @return a {@code Collector} which collects 0 or 1 input @{code Long} elements into an * {@code OptionalLong}. */ public static Collector<Long, ?, OptionalLong> toOptionalLong() { return toOptional(OptionalLong::empty, OptionalLong::of); }
static <T, OPT_T> OptionalBuilder<T, OPT_T> combine(OptionalBuilder<T, OPT_T> left, OptionalBuilder<T, OPT_T> right) { if (left.set && right.set) { throw tooManyValues(left.value, right.value); } return left.set ? left : right; }
/** * Obtain a collector for the given type. * * @param containerType the container type. * @return a Collector for the given container type, or empty null if no collector is registered for the given type. */ public Optional<Collector<?, ?, ?>> findFor(Type containerType) { return findFactoryFor(containerType) .map(f -> f.build(containerType)); }
/** * Returns the element type for the given container type. * * @param containerType the container type. * @return the element type for the given container type, if available. */ public Optional<Type> findElementTypeFor(Type containerType) { return findFactoryFor(containerType) .flatMap(f -> f.elementType(containerType)); }
/** * Obtain a collector for the given type. * * @param containerType the container type. * @return a Collector for the given container type, or empty null if no collector is registered for the given type. */ public Optional<Collector<?, ?, ?>> findCollectorFor(Type containerType) { return getConfig(JdbiCollectors.class).findFor(containerType); }
/** * Returns the element type for the given container type. * * @param containerType the container type. * @return the element type for the given container type, if available. */ public Optional<Type> findElementTypeFor(Type containerType) { return getConfig(JdbiCollectors.class).findElementTypeFor(containerType); }
/** * Convenience method for {@code getConfig(JdbiCollectors.class).register(factory)} * * @param factory collector factory * @return this */ default This registerCollector(CollectorFactory factory) { return configure(JdbiCollectors.class, c -> c.register(factory)); }
/** * Returns a {@code Collector} that accumulates {@code Map.Entry<K, V>} input elements into a * {@code HashBiMap<K, V>}. 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 * @return a {@code Collector} which collects map entry elements into a {@code HashBiMap}, * in encounter order. */ public static <K, V> Collector<Map.Entry<K, V>, ?, BiMap<K, V>> toHashBiMap() { return toMap(HashBiMap::create); }
@Override public JdbiCollectors createCopy() { return new JdbiCollectors(this); } }
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; } }
@Test public void maps() { testMapType(new GenericType<Map<Long, String>>() {}); testMapType(new GenericType<HashMap<Long, String>>() {}); testMapType(new GenericType<LinkedHashMap<Long, String>>() {}); testMapType(new GenericType<SortedMap<Long, String>>() {}); testMapType(new GenericType<TreeMap<Long, String>>() {}); testMapType(new GenericType<ConcurrentMap<Long, String>>() {}); testMapType(new GenericType<ConcurrentHashMap<Long, String>>() {}); testMapType(new GenericType<WeakHashMap<Long, String>>() {}); }
/** * Returns a {@code Collector} that accumulates 0 or 1 input elements into an {@code Option<T>}. * The returned collector will throw {@code IllegalStateException} whenever 2 or more elements * are present in a stream. Null elements are mapped to {@code Option.none()}. * * @param <T> the collected type * @return a {@code Collector} which collects 0 or 1 input elements into an {@code Option<T>}. */ public static <T> Collector<T, ?, Option<T>> toOption() { return OptionalCollectors.toOptional(Option::none, Option::of); } }
MapCollectorFactory() { collectors.put(Map.class, toMap(LinkedHashMap::new)); collectors.put(HashMap.class, toMap(HashMap::new)); collectors.put(LinkedHashMap.class, toMap(LinkedHashMap::new)); collectors.put(SortedMap.class, toMap(TreeMap::new)); collectors.put(TreeMap.class, toMap(TreeMap::new)); collectors.put(ConcurrentMap.class, toMap(ConcurrentHashMap::new)); collectors.put(ConcurrentHashMap.class, toMap(ConcurrentHashMap::new)); collectors.put(WeakHashMap.class, toMap(WeakHashMap::new)); }
void set(T value) { if (set) { throw tooManyValues(this.value, value); } this.value = value; this.set = true; }
/** * Returns a {@code Collector} that accumulates 0 or 1 input elements into Guava's {@code Optional<T>}. * The returned collector will throw {@code IllegalStateException} whenever 2 or more elements * are present in a stream. Null elements are mapped to {@code Optional.absent()}. * * @param <T> the collected type * @return a {@code Collector} which collects 0 or 1 input elements into a Guava {@code Optional<T>}. */ public static <T> Collector<T, ?, Optional<T>> toOptional() { return OptionalCollectors.toOptional(Optional::absent, Optional::of); }
/** * 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. Null elements are mapped to {@code Optional.empty()}. * * @param <T> the collected type * @return a {@code Collector} which collects 0 or 1 input elements into an {@code Optional<T>}. */ public static <T> Collector<T, ?, Optional<T>> toOptional() { return toOptional(Optional::empty, Optional::of); }
@Override public Collector<?, ?, ?> build(Type containerType) { return toOptional(); } }
/** * Returns a {@code Collector} that accumulates 0 or 1 input {@code Integer} elements into an * {@code OptionalInt}. The returned collector will throw {@code IllegalStateException} whenever * 2 or more elements are present in a stream. Null elements are mapped to * {@code OptionalInt.empty()}. * * @return a {@code Collector} which collects 0 or 1 input {@code Integer} elements into an * {@code OptionalInt}. */ public static Collector<Integer, ?, OptionalInt> toOptionalInt() { return toOptional(OptionalInt::empty, OptionalInt::of); }
/** * Returns a {@code Collector} that accumulates 0 or 1 input {@code Double} elements into an * {@code OptionalDouble}. The returned collector will throw {@code IllegalStateException} * whenever 2 or more elements are present in a stream. Null elements are mapped to * {@code OptionalDouble.empty()}. * * @return a {@code Collector} which collects 0 or 1 input @{code Double} elements into an * {@code OptionalDouble}. */ public static Collector<Double, ?, OptionalDouble> toOptionalDouble() { return toOptional(OptionalDouble::empty, OptionalDouble::of); }