package io.cattle.platform.util.type;
import io.cattle.platform.archaius.util.ArchaiusUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
public class CollectionUtils {
public static Object getNestedValue(Object map, String... keys) {
Object value = map;
for (String key : keys) {
Map<String, Object> mapObject = CollectionUtils.toMap(value);
value = mapObject.get(key);
}
return value;
}
@SuppressWarnings("unchecked")
public static <T> void setNestedValue(Map<T, Object> map, Object value, T... keys) {
for (int i = 0; i < keys.length; i++) {
T key = keys[i];
if (key == null) {
return;
}
if (i == keys.length - 1) {
map.put(keys[i], value);
} else {
Map<T, Object> nestedMap = (Map<T, Object>) map.get(keys[i]);
if (nestedMap == null) {
nestedMap = new HashMap<T, Object>();
map.put(key, nestedMap);
}
map = nestedMap;
}
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <K, V extends Collection<T>, T> void addToMap(Map<K, V> data, K key, T value, Class<? extends Collection> clz) {
V values = data.get(key);
if (values == null) {
try {
values = (V) clz.newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException("Failed to create collection class", e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Failed to create collection class", e);
}
data.put(key, values);
}
values.add(value);
}
public static List<?> toList(Object obj) {
if (obj instanceof List) {
return (List<?>) obj;
} else if (obj == null) {
return Collections.emptyList();
} else {
return Arrays.asList(obj);
}
}
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> toMap(Object obj) {
if (obj == null) {
return new HashMap<K, V>();
}
if (obj instanceof Map) {
return (Map<K, V>) obj;
} else {
return new HashMap<K, V>();
}
}
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> castMap(Object obj) {
if (obj == null) {
return new HashMap<K, V>();
}
if (obj instanceof Map) {
return (Map<K, V>) obj;
} else {
throw new IllegalArgumentException("Expected [" + obj + "] to be a Map");
}
}
@SuppressWarnings("unchecked")
public static <T> Map<T, Object> asMap(T key, Object... values) {
Map<T, Object> result = new LinkedHashMap<T, Object>();
if (values == null || values.length % 2 == 0) {
throw new IllegalArgumentException("value[] must be not null and an odd length");
}
result.put(key, values[0]);
for (int i = 1; i < values.length; i += 2) {
result.put((T) values[i], values[i + 1]);
}
return result;
}
private static List<?> getObjectsByName(Map<String, Object> objectByName, String name) {
Object obj = objectByName.get(name);
if (obj == null) {
return Collections.emptyList();
}
return Arrays.asList(obj);
}
@SuppressWarnings("unchecked")
public static synchronized <T> List<T> orderList(Class<?> clz, List<T> objects) {
String key = NamedUtils.toDotSeparated(clz.getSimpleName());
Map<String, Object> objectsByName = new HashMap<>();
final Map<Object, String> objectToName = new HashMap<>();
if (objects != null) {
for (T obj : objects) {
String name = NamedUtils.getName(obj);
objectsByName.put(name, obj);
objectToName.put(obj, name);
}
}
Set<String> excludes = getSetting(key + ".exclude");
String list = ArchaiusUtil.getString(key + ".list").get();
if (!StringUtils.isBlank(list)) {
List<Object> result = new ArrayList<Object>();
for (String name : list.split("\\s*,\\s*")) {
if (excludes.contains(name)) {
continue;
}
result.addAll(getObjectsByName(objectsByName, name));
}
return (List<T>) result;
}
Set<String> includes = getSetting(key + ".include");
Set<Object> ordered = new TreeSet<Object>(new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
int left = PriorityUtils.getPriority(o1);
int right = PriorityUtils.getPriority(o2);
if (left < right) {
return -1;
} else if (left > right) {
return 1;
}
String leftName = objectToName.get(o1);
String rightName = objectToName.get(o2);
int comparisonResult = leftName.compareTo(rightName);
if (comparisonResult == 0 && !o1.equals(o2)) {
throw new RuntimeException("Trying to add 2 objects with the same name: " + leftName + ". Second object is ignored!");
}
return comparisonResult;
}
});
if (objects != null) {
ordered.addAll(objects);
}
for (String include : includes) {
ordered.addAll(getObjectsByName(objectsByName, include));
}
Iterator<Object> iter = ordered.iterator();
while (iter.hasNext()) {
String name = objectToName.get(iter.next());
if (excludes.contains(name)) {
iter.remove();
}
}
return (List<T>) new ArrayList<Object>(ordered);
}
private static Set<String> getSetting(String key) {
String value = getSettingValue(key);
if (StringUtils.isBlank(value)) {
return Collections.emptySet();
}
Set<String> result = new HashSet<String>();
for (String part : value.trim().split("\\s*,\\s*")) {
result.add(part);
}
return result;
}
private static String getSettingValue(String key) {
return ArchaiusUtil.getString(key).get();
}
}