@SuppressWarnings("unchecked") @Override public <P> Collection<P> getParts(Class<? extends P> partInterface) { return (Collection<P>) parts.get(partInterface); }
private void registerPart(Object part, Class<?>[] implementedInterfaces, Class<?> predecessor, Object successor) { for (Class<?> iFace : implementedInterfaces) { if (successor == null) { parts.put(iFace, part); if (predecessor != null) { synchronized (parts) { parts.getUnderlyingMap().get(iFace).removeIf(p -> p.getClass().equals(predecessor)); } } } else { synchronized (parts) { Collection<Object> partList = parts.getUnderlyingMap().get(iFace); if (partList == null || !partList.contains(successor)) { parts.put(iFace, part); } } } } }
/** * Creates a new <tt>MultiMap</tt> for the specified types which is not thread safe. * * @param <K> the type of the keys used in the map * @param <V> the type of the values used withing the value lists of the map * @return a new instance of <tt>MultiMap</tt> which is not thread safe. */ public static <K, V> MultiMap<K, V> create() { return new MultiMap<>(new HashMap<K, Collection<V>>()); }
/** * Creates a {@link Collector} which can be used to group a stream into a multi map. * * @param supplier the factory for creating the result map * @param classifier the method used to extract the key from the elements * @param <K> the extracted key type of the map * @param <V> the value type of the incoming stream and outgoing map * @return a <tt>Collector</tt> to be used with {@link Stream#collect(java.util.stream.Collector)} */ public static <K, V> Collector<V, MultiMap<K, V>, MultiMap<K, V>> groupingBy(Supplier<MultiMap<K, V>> supplier, Function<V, K> classifier) { return Collector.of(supplier, (map, value) -> map.put(classifier.apply(value), value), (a, b) -> a.merge(b), Function.identity(), Collector.Characteristics.IDENTITY_FINISH); }
private Collection<Transformer<?, ?>> getFactories(Class<?> sourceType, Class<?> targetType) { if (factories == null) { MultiMap<Tuple<Class<?>, Class<?>>, Transformer<?, ?>> result = MultiMap.createOrdered(); for (Transformer<?, ?> factory : factoryList) { result.put(Tuple.create(factory.getSourceClass(), factory.getTargetClass()), factory); } factories = result; } return factories.get(Tuple.create(sourceType, targetType)); }
@SuppressWarnings("unchecked") private static Collection<Class<?>> getMixins(Class<? extends Mixable> forClass) { if (allMixins == null) { MultiMap<Class<? extends Mixable>, Class<?>> mixinMap = MultiMap.create(); for (Class<?> mixinClass : Injector.context().getParts(Mixin.class, Class.class)) { Class<?> target = mixinClass.getAnnotation(Mixin.class).value(); if (Mixable.class.isAssignableFrom(target)) { mixinMap.put((Class<? extends Mixable>) target, mixinClass); } else { Mixing.LOG.WARN("Mixing class '%s' has a non mixable target class (%s). Skipping mixin.", mixinClass.getName(), target.getName()); } } allMixins = mixinMap; } return allMixins.get(forClass); }
MultiMap<String, Table> targetByRealm = MultiMap.create(); for (EntityDescriptor ed : mixing.getDesciptors()) { if (SQLEntity.class.isAssignableFrom(ed.getType())) { if (databases.containsKey(ed.getRealm())) { targetByRealm.put(ed.getRealm(), createTable(ed)); for (Map.Entry<String, Collection<Table>> target : targetByRealm.getUnderlyingMap().entrySet()) { try { Extension ext = Sirius.getSettings().getExtension(EXTENSION_MIXING_JDBC, target.getKey());
/** * Removes all entries from this map */ public void clear() { getUnderlyingMap().clear(); }
@Override @SuppressWarnings("squid:S1185") @Explain("We need to overwrite this to make it synchronized.") public synchronized void put(K key, V value) { super.put(key, value); }
Microtiming.getTimings() .stream() .collect(MultiMap.groupingBy(MultiMap::create, Microtiming.Timing::getCategory)) .stream() .forEach(c -> { output.line(c.getKey());
/** * Adds the given value to the list of values kept for the given key. * <p> * Note that the values for a given key don't from a <tt>Set</tt>. Therefore adding the same value twice * for the same key, will result in having a value list containing the added element twice. * * @param key the key for which the value is added to the map * @param value the value which is added to the list of values for this key */ public void put(@Nonnull K key, @Nullable V value) { Collection<V> list = base.computeIfAbsent(key, k -> createValueList()); list.add(value); }
/** * Creates a {@link Collector} which can be used to group a stream into a multi map. * <p> * This method permits the classifier function to return multiple keys for a single element. The element will * be added for all returned keys. * * @param supplier the factory for creating the result map * @param classifier the method used to extract the keys from the elements * @param <K> the extracted key type of the map * @param <V> the value type of the incoming stream and outgoing map * @return a <tt>Collector</tt> to be used with {@link Stream#collect(java.util.stream.Collector)} */ public static <K, V> Collector<V, MultiMap<K, V>, MultiMap<K, V>> groupingByMultiple(Supplier<MultiMap<K, V>> supplier, Function<V, Collection<K>> classifier) { return Collector.of(supplier, (map, value) -> classifier.apply(value).forEach(key -> map.put(key, value)), (a, b) -> a.merge(b), Function.identity(), Collector.Characteristics.IDENTITY_FINISH); }
/** * Boilerplate method to access all entries of this map as {@link Stream}. * <p> * <b>Note</b>: Calling {@link sirius.kernel.commons.Tuple#flatten(java.util.Map.Entry)} via * {@link Stream#flatMap(java.util.function.Function)} will transform the resulting stream into a stream of * all pairs represented by this map. * * @return a <tt>Stream</tt> containing all entries of this map */ public Stream<Map.Entry<K, Collection<V>>> stream() { return getUnderlyingMap().entrySet().stream(); } }
/** * Merges the given multi map into this one. * <p> * If both maps contain values for the same key, to lists will be joined together. * <p> * <b>Note</b>: This will modify the callee instead of creating a new result map * * @param other the other map to merge into this one * @return the callee itself for further processing */ public MultiMap<K, V> merge(MultiMap<K, V> other) { if (other != null) { other.base.entrySet().stream().flatMap(Tuple::flatten).forEach(t -> put(t.getFirst(), t.getSecond())); } return this; }
/** * Sets the given value to the given name. * <p> * All previously set values will be removed. * * @param key the key for which the value is added to the map * @param value the name (and only) value for the given key */ public void set(@Nonnull K key, @Nullable V value) { Collection<V> list = base.get(key); if (list == null) { list = createValueList(); base.put(key, list); } else { list.clear(); } list.add(value); }
/** * Provides a {@link Collector} which can be used to collect a {@link Stream} of tuples into a {@link MultiMap}. * <p> * The type of <tt>MultiMap</tt> used can be determined by the <tt>supplier</tt>. So for example * {@code MultiMap::createOrdered} will create a map with ordered keys. * * @param supplier factory for generating the result map * @param <K> key type of the tuples being processed * @param <V> value type of the tuples being processed * @return a <tt>Collector</tt> which transforms a stream of tuples into a multi map */ public static <K, V> Collector<Tuple<K, V>, MultiMap<K, V>, MultiMap<K, V>> toMultiMap(Supplier<MultiMap<K, V>> supplier) { return Collector.of(supplier, (map, tuple) -> map.put(tuple.getFirst(), tuple.getSecond()), (a, b) -> a.merge(b), Function.identity(), Collector.Characteristics.IDENTITY_FINISH); }
/** * Returns a list of all values for all keys. * <p> * Note that this list has no <tt>Set</tt> like behaviour. Therefore the same value might occur several times * if it was added more than once for the same or for different keys. * * @return a list of all values stored for all keys */ @Nonnull public List<V> values() { List<V> result = new ArrayList<>(); for (Collection<V> val : getUnderlyingMap().values()) { result.addAll(val); } return result; }
@SuppressWarnings("unchecked") @Override public <L, P> Collection<P> getParts(@Nonnull Class<L> lookupClass, @Nonnull Class<? extends P> partType) { return (Collection<P>) parts.get(lookupClass); }
/** * Creates a new <tt>MultiMap</tt> for the specified types which is not thread safe but keeps its insertion order. * * @param <K> the type of the keys used in the map * @param <V> the type of the values used withing the value lists of the map * @return a new instance of <tt>MultiMap</tt> which is not thread safe. */ public static <K, V> MultiMap<K, V> createOrdered() { return new MultiMap<>(new LinkedHashMap<K, Collection<V>>()); }
@Override public synchronized void registerDynamicPart(String uniqueName, Object part, Class<?> lookupClass) { Map<String, Object> partsOfClass = namedParts.get(lookupClass); if (partsOfClass != null) { Object originalPart = partsOfClass.get(uniqueName); if (originalPart != null) { partsOfClass.remove(uniqueName); Collection<Object> specificParts = parts.getUnderlyingMap().get(lookupClass); if (specificParts != null) { specificParts.remove(originalPart); } } } registerPart(uniqueName, part, lookupClass); }