org.apache.sshd.common.util.MapEntryUtils Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.sshd.common.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.TreeMap;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
/**
* Represents an un-modifiable pair of values
*
* @author Apache MINA SSHD Project
*/
public final class MapEntryUtils {
@SuppressWarnings({ "rawtypes", "unchecked" })
private static final Comparator> BY_KEY_COMPARATOR = (o1, o2) -> {
Comparable k1 = o1.getKey();
Comparable k2 = o2.getKey();
return k1.compareTo(k2);
};
@SuppressWarnings("rawtypes")
private static final Supplier CASE_INSENSITIVE_MAP_FACTORY = () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private MapEntryUtils() {
throw new UnsupportedOperationException("No instance");
}
/**
* @param The {@link Comparable} key type
* @param The associated entry value
* @return A {@link Comparator} for {@link java.util.Map.Entry}-ies that compares the key values
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static , V> Comparator> byKeyEntryComparator() {
return (Comparator) BY_KEY_COMPARATOR;
}
public static class GenericMapPopulator> implements Supplier {
private final M map;
public GenericMapPopulator(M map) {
this.map = Objects.requireNonNull(map, "No map provided");
}
public GenericMapPopulator put(K k, V v) {
if (v == null) {
return remove(k);
}
map.put(Objects.requireNonNull(k, "No key provided"), v);
return this;
}
public GenericMapPopulator remove(K k) {
map.remove(k);
return this;
}
public GenericMapPopulator putAll(Map extends K, ? extends V> other) {
if (isNotEmpty(other)) {
other.forEach(this::put);
}
return this;
}
public GenericMapPopulator clear() {
map.clear();
return this;
}
@Override
public M get() {
return map;
}
}
public static class MapBuilder extends GenericMapPopulator> {
public MapBuilder() {
super(new LinkedHashMap<>());
}
@Override
public MapBuilder put(K k, V v) {
super.put(k, v);
return this;
}
@Override
public MapBuilder remove(K k) {
super.remove(k);
return this;
}
@Override
public MapBuilder putAll(Map extends K, ? extends V> other) {
super.putAll(other);
return this;
}
@Override
public MapBuilder clear() {
super.clear();
return this;
}
public Map build() {
return get();
}
public Map immutable() {
return Collections.unmodifiableMap(build());
}
public static MapBuilder builder() {
return new MapBuilder<>();
}
}
public static class NavigableMapBuilder extends GenericMapPopulator> {
public NavigableMapBuilder(Comparator super K> comparator) {
super(new TreeMap<>(Objects.requireNonNull(comparator, "No comparator provided")));
}
@Override
public NavigableMapBuilder put(K k, V v) {
super.put(k, v);
return this;
}
@Override
public NavigableMapBuilder remove(K k) {
super.remove(k);
return this;
}
@Override
public NavigableMapBuilder putAll(Map extends K, ? extends V> other) {
super.putAll(other);
return this;
}
@Override
public NavigableMapBuilder clear() {
super.clear();
return this;
}
public NavigableMap build() {
return get();
}
public NavigableMap immutable() {
return Collections.unmodifiableNavigableMap(build());
}
public static , V> NavigableMapBuilder builder() {
return builder(Comparator.naturalOrder());
}
public static NavigableMapBuilder builder(Comparator super K> comparator) {
return new NavigableMapBuilder<>(comparator);
}
}
public static class EnumMapBuilder, V> extends GenericMapPopulator> {
public EnumMapBuilder(Class keyType) {
super(new EnumMap<>(Objects.requireNonNull(keyType, "No enum class specified")));
}
@Override
public EnumMapBuilder put(K k, V v) {
super.put(k, v);
return this;
}
@Override
public EnumMapBuilder remove(K k) {
super.remove(k);
return this;
}
@Override
public EnumMapBuilder putAll(Map extends K, ? extends V> other) {
super.putAll(other);
return this;
}
@Override
public EnumMapBuilder clear() {
super.clear();
return this;
}
public Map build() {
return get();
}
public Map immutable() {
return Collections.unmodifiableMap(build());
}
public static , V> EnumMapBuilder builder(Class keyType) {
return new EnumMapBuilder<>(keyType);
}
}
public static int size(Map, ?> m) {
return (m == null) ? 0 : m.size();
}
public static boolean isEmpty(Map, ?> m) {
return size(m) <= 0;
}
public static boolean isNotEmpty(Map, ?> m) {
return !isEmpty(m);
}
/**
* @param Type of mapped value
* @return A {@link Supplier} that returns a new {@link NavigableMap} whenever its {@code get()} method
* is invoked
*/
@SuppressWarnings("unchecked")
public static Supplier> caseInsensitiveMap() {
return CASE_INSENSITIVE_MAP_FACTORY;
}
/**
* Flips between keys and values of an input map
*
* @param Original map key type
* @param Original map value type
* @param Flipped map type
* @param map The original map to flip
* @param mapCreator The creator of the target map
* @param allowDuplicates Whether to ignore duplicates on flip
* @return The flipped map result
* @throws IllegalArgumentException if allowDuplicates is {@code false} and a duplicate value found in the
* original map.
*/
public static > M flipMap(
Map extends K, ? extends V> map, Supplier extends M> mapCreator, boolean allowDuplicates) {
M result = Objects.requireNonNull(mapCreator.get(), "No map created");
map.forEach((key, value) -> {
K prev = result.put(value, key);
if ((prev != null) && (!allowDuplicates)) {
ValidateUtils.throwIllegalArgumentException("Multiple values for key=%s: current=%s, previous=%s", value, key,
prev);
}
});
return result;
}
@SafeVarargs
public static > M mapValues(
Function super V, ? extends K> keyMapper, Supplier extends M> mapCreator, V... values) {
return mapValues(keyMapper, mapCreator, GenericUtils.isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
}
/**
* Creates a map out of a group of values
*
* @param The key type
* @param The value type
* @param The result {@link Map} type
* @param keyMapper The {@link Function} that generates a key for a given value. If the returned key is
* {@code null} then the value is not mapped
* @param mapCreator The {@link Supplier} used to create/retrieve the result map - provided non-empty group of
* values
* @param values The values to be mapped
* @return The resulting {@link Map} - Note: no validation is made to ensure that 2 (or more)
* values are not mapped to the same key
*/
public static > M mapValues(
Function super V, ? extends K> keyMapper,
Supplier extends M> mapCreator,
Collection extends V> values) {
M map = mapCreator.get();
for (V v : values) {
K k = keyMapper.apply(v);
if (k == null) {
continue; // debug breakpoint
}
map.put(k, v);
}
return map;
}
public static NavigableMap toSortedMap(
Iterable extends T> values, Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper, Comparator super K> comparator) {
return GenericUtils.stream(values).collect(toSortedMap(keyMapper, valueMapper, comparator));
}
public static Collector> toSortedMap(
Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper,
Comparator super K> comparator) {
return Collectors.toMap(keyMapper, valueMapper, throwingMerger(), () -> new TreeMap<>(comparator));
}
public static BinaryOperator throwingMerger() {
return (u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
};
}
}