@SuppressWarnings("unchecked") @Override public M merge(Multimap<? extends K, ? extends V> that) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return (M) createFromEntries(that); } else if (that.isEmpty()) { return (M) this; } else { return that.foldLeft((M) this, (map, entry) -> (M) map.put(entry)); } }
@SuppressWarnings("unchecked") @Override public <K2 extends K, V2 extends V> M merge(Multimap<K2, V2> that, BiFunction<Traversable<V>, Traversable<V2>, Traversable<V>> collisionResolution) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(collisionResolution, "collisionResolution is null"); if (isEmpty()) { return (M) createFromEntries(that); } else if (that.isEmpty()) { return (M) this; } else { final Map<K, Traversable<V>> result = that.keySet().foldLeft(this.back, (map, key) -> { final Traversable<V> thisValues = map.get(key).getOrElse((Traversable<V>) emptyContainer.get()); final Traversable<V2> thatValues = that.get(key).get(); final Traversable<V> newValues = collisionResolution.apply(thisValues, thatValues); return map.put(key, newValues); }); return (M) createFromMap(result); } }
@Override public boolean isDefinedAt(K key) { return containsKey(key); } };
@SuppressWarnings("unchecked") static <K, V> boolean equals(Multimap<K, V> source, Object object) { if (source == object) { return true; } else if (source != null && object instanceof Multimap) { final Multimap<K, V> multimap = (Multimap<K, V>) object; if (source.size() != multimap.size()) { return false; } else { try { return source.forAll(multimap::contains); } catch (ClassCastException e) { return false; } } } else { return false; } }
@SuppressWarnings("unchecked") static <T, K, V, M extends Multimap<K, V>> M ofStream(M source, java.util.stream.Stream<? extends T> stream, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends V> valueMapper) { Objects.requireNonNull(stream, "stream is null"); Objects.requireNonNull(keyMapper, "keyMapper is null"); Objects.requireNonNull(valueMapper, "valueMapper is null"); return Stream.ofAll(stream).foldLeft(source, (m, el) -> (M) m.put(keyMapper.apply(el), valueMapper.apply(el))); }
@Deprecated @Override default Traversable<V> apply(K key) { return get(key).getOrElseThrow(NoSuchElementException::new); }
@Override Object toJavaObj(Multimap<?, ?> value) throws IOException { final LinkedHashMap<Object, List<Object>> result = new LinkedHashMap<>(); value.forEach(e -> { List<Object> list = result.get(e._1); if (list == null) { list = new ArrayList<>(); result.put(e._1, list); } list.add(e._2); }); return result; }
public ResourceRepresentation<V> withRepresentation( String rel, ResourceRepresentation<?> resource) { if (resources.containsValue(resource)) { throw new IllegalStateException("Resource is already embedded."); } Support.checkRelType(rel); validateSingletonRel(rel); Multimap<String, ResourceRepresentation<?>> updatedResources = resources.put(rel, resource); ResourceRepresentation<V> updatedRepresentation = new ResourceRepresentation<>( content, links, rels, namespaceManager, value, updatedResources); // Propagate null property flag to parent. if (resource.hasNullProperties()) { updatedRepresentation.hasNullProperties = true; } if (!rels.containsKey(rel)) { updatedRepresentation = updatedRepresentation.withRel(Rels.natural(rel)); } return updatedRepresentation; }
@Override public boolean isEmpty(SerializerProvider provider, Multimap<?, ?> value) { return value.isEmpty(); } }
@Test public void testMultimapValuesAddAnotherDataSetShouldHave2ValuesForEachKey() { final int offset = 10; for (Integer i : expected) { dbRule.getSharedHandle().execute("insert into something(name, intValue) values (?, ?)", Integer.toString(i + offset) + "asString", i); } Multimap<Integer, String> result = dbRule.getSharedHandle().createQuery("select intValue, name from something") .collectInto(new GenericType<Multimap<Integer, String>>() {}); assertThat(result).hasSize(expected.size() * 2); expected.forEach(i -> assertThat(result.apply(i)) .containsOnlyElementsOf(List.of(i + "asString", (i + 10) + "asString"))); } }
@SuppressWarnings("unchecked") static <K, V, M extends Multimap<K, V>> M ofJavaMap(M source, java.util.Map<? extends K, ? extends V> map) { Objects.requireNonNull(map, "map is null"); return Stream.ofAll(map.entrySet()).foldLeft(source, (m, el) -> (M) m.put(el.getKey(), el.getValue())); }
@Override public Traversable<V> apply(K key) { return get(key).getOrElseThrow(NoSuchElementException::new); } @Override
private static String expectedMultimapJson(Multimap<?, ?> multimap, int opts) { final LinkedHashMap<Object, List<Object>> map = new LinkedHashMap<>(); multimap.forEach(e -> { List<Object> list = map.computeIfAbsent(e._1, k -> new ArrayList<>()); list.add(e._2); }); StringBuilder sb = new StringBuilder("{"); map.forEach((k, l) -> sb.append(expectedJson(k.toString(), opts)).append(":").append(expectedJson(io.vavr.collection.Stream.ofAll(l)))); sb.append("}"); return sb.toString(); }
@SuppressWarnings("unchecked") static <K, V> boolean equals(Multimap<K, V> source, Object object) { if (source == object) { return true; } else if (source != null && object instanceof Multimap) { final Multimap<K, V> multimap = (Multimap<K, V>) object; if (source.size() != multimap.size()) { return false; } else { try { return source.forAll(multimap::contains); } catch (ClassCastException e) { return false; } } } else { return false; } }
@Test public void testNonUniqueIndexWithMultimap() { Handle h = dbRule.getSharedHandle(); h.execute("create table user (id int, name varchar)"); h.prepareBatch("insert into user (id, name) values (?, ?)") .add(1, "alice") .add(2, "bob") .add(3, "alice") .execute(); Multimap<String, User> usersByName = h.createQuery("select * from user") .setMapKeyColumn("name") .registerRowMapper(ConstructorMapper.factory(User.class)) .collectInto(new GenericType<Multimap<String, User>>() {}); assertThat(usersByName.apply("alice")).hasSize(2).containsExactly( new User(1, "alice"), new User(3, "alice") ); assertThat(usersByName.apply("bob")).hasSize(1).containsExactly( new User(2, "bob") ); }
@Override public <K2, V2> Multimap<K2, V2> map(BiFunction<? super K, ? super V, Tuple2<K2, V2>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return foldLeft(this.emptyInstance(), (acc, entry) -> acc.put(mapper.apply(entry._1, entry._2))); }
@SuppressWarnings("unchecked") @Override public M merge(Multimap<? extends K, ? extends V> that) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return (M) createFromEntries(that); } else if (that.isEmpty()) { return (M) this; } else { return that.foldLeft((M) this, (map, entry) -> (M) map.put(entry)); } }
@SuppressWarnings("unchecked") @Override public <K2 extends K, V2 extends V> M merge(Multimap<K2, V2> that, BiFunction<Traversable<V>, Traversable<V2>, Traversable<V>> collisionResolution) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(collisionResolution, "collisionResolution is null"); if (isEmpty()) { return (M) createFromEntries(that); } else if (that.isEmpty()) { return (M) this; } else { final Map<K, Traversable<V>> result = that.keySet().foldLeft(this.back, (map, key) -> { final Traversable<V> thisValues = map.get(key).getOrElse((Traversable<V>) emptyContainer.get()); final Traversable<V2> thatValues = that.get(key).get(); final Traversable<V> newValues = collisionResolution.apply(thisValues, thatValues); return map.put(key, newValues); }); return (M) createFromMap(result); } }
@Override default boolean contains(Tuple2<K, V> element) { return get(element._1).map(v -> v.contains(element._2)).getOrElse(false); }