package alien4cloud.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.helpers.FormattingTuple;
import org.slf4j.helpers.MessageFormatter;
import com.google.common.collect.Maps;
import alien4cloud.exception.NotFoundException;
import lombok.SneakyThrows;
public final class AlienUtils {
public static final String DEFAULT_PREFIX_SEPARATOR = "_";
public static final String COLON_SEPARATOR = ":";
private AlienUtils() {
}
/**
* Utility method to iterate over a list that can be null<br>
* for(T element : safe(list)) {}
* <br>
* <br>
* ATTENTION: Use this method for readonly operation only
*
* @param collection The list that may be null.
* @param <T> The type of list inner elements
* @return The list of an empty list.
*/
public static <T> Collection<T> safe(Collection<T> collection) {
return org.apache.commons.collections4.CollectionUtils.emptyIfNull(collection);
}
/**
* Utility method to iterate over a map that can be null<br>
* for(T element : safe(list)) {}
* <br>
* <br>
* ATTENTION: Use this method for readonly operation only
*
* @param map The list that may be null.
* @param <K> The type of map keys
* @param <K> The type of map values
* @return The map of an empty map.
*/
public static <K, V> Map<K, V> safe(Map<K, V> map) {
return org.apache.commons.collections4.MapUtils.emptyIfNull(map);
}
/**
* Get an element from the map (that can be null) or throw a NotFoundException if the element is not in the map.
*
* @param map The map from which to get the element or null.
* @param key The key of the element.
* @param <K> The type of map keys
* @param <K> The type of map values
* @return A non null element.
*/
public static <K, V> V getOrFail(Map<K, V> map, K key) {
return getOrFail(map, key, "The element with key <{}> cannot be found", key.toString());
}
/**
* Get an element from the map (that can be null) or throw a NotFoundException if the element is not in the map.
*
* @param map The map from which to get the element or null.
* @param key The key of the element.
* @param message The error message for the not found exception. The message supports same formatting as logs "This is message {}", "message".
* @param args The arguments for the message formatting.
* @param <K> The type of map keys
* @param <K> The type of map values
* @return A non null element.
*/
public static <K, V> V getOrFail(Map<K, V> map, K key, String message, Object... args) {
if (map == null) {
FormattingTuple ft = MessageFormatter.arrayFormat(message, args);
throw new NotFoundException(ft.getMessage());
}
V value = map.get(key);
if (value == null) {
FormattingTuple ft = MessageFormatter.arrayFormat(message, args);
throw new NotFoundException(ft.getMessage());
}
return value;
}
/**
* Shortcurt to create an array of elements.
*
* @param elements The elements for which to create an array.
* @param <T> The type of the elements (and array)
* @return An array of the given elements.
*/
public static <T> T[] array(T... elements) {
return elements;
}
/**
* Shortcurt to create an array of array of elements.
*
* @param elements The elements for which to create an array.
* @param <T> The type of the elements (and array)
* @return An array of the given elements.
*/
public static <T> T[][] arOfArray(T[]... elements) {
return elements;
}
/**
* Fill an array with data from an untyped collection. Both must have the same size.
*
* @param array The array in which to insert elements.
* @param collection The untyped collection that contains elements to put in the array.
* @param <T> Type of elements in the array (should be the same in collection)
* @return The filled array.
*/
public static <T> T[] fill(T[] array, Collection collection) {
if (array.length != collection.size()) {
throw new IllegalArgumentException("Size of array and collection must be the same.");
}
int i = 0;
for (Object element : collection) {
array[i] = (T) element;
i++;
}
return array;
}
public static String putValueCommaSeparatedInPosition(String values, String valueToPut, int position) {
String[] valuesArray;
String separator = ",";
int positionInArray = position - 1;
if (StringUtils.isBlank(values)) {
valuesArray = new String[0];
} else {
valuesArray = values.split(separator);
}
StringBuilder toReturnBuilder = new StringBuilder("");
if (valuesArray.length >= position) {
valuesArray[positionInArray] = valueToPut;
String separatorToAppend;
for (int i = 0; i < valuesArray.length; i++) {
separatorToAppend = i + 1 == valuesArray.length ? "" : ",";
toReturnBuilder.append(valuesArray[i]).append(separatorToAppend);
}
} else {
int nbSeparatorToAdd = 0;
if (StringUtils.isBlank(values)) {
toReturnBuilder = new StringBuilder("");
nbSeparatorToAdd = position - 1;
} else {
toReturnBuilder = new StringBuilder(values);
nbSeparatorToAdd = position - valuesArray.length;
}
for (int i = 0; i < nbSeparatorToAdd; i++) {
toReturnBuilder.append(separator);
}
toReturnBuilder.append(valueToPut);
}
return toReturnBuilder.toString();
}
/**
* prefix a string with another
*
* @param separator
* @param toPrefix
* @param prefixes
* @return
*/
public static String prefixWith(String separator, String toPrefix, String... prefixes) {
if (toPrefix == null) {
return null;
}
if (ArrayUtils.isEmpty(prefixes)) {
return toPrefix;
}
String finalSeparator = separator == null ? DEFAULT_PREFIX_SEPARATOR : separator;
StringBuilder builder = new StringBuilder();
for (String prefix : prefixes) {
builder.append(prefix).append(finalSeparator);
}
return builder.append(toPrefix).toString();
}
/**
* prefix a string with another using the default separator "_"
*
* @param toPrefix
* @param prefixes
* @return
*/
public static String prefixWithDefaultSeparator(String toPrefix, String... prefixes) {
return prefixWith(DEFAULT_PREFIX_SEPARATOR, toPrefix, prefixes);
}
@SuppressWarnings("unchecked")
@SneakyThrows({ IllegalAccessException.class, InvocationTargetException.class })
public static <K, V> Map<K, V> fromListToMap(List<V> list, String keyProperty, boolean useGetter) {
if (list == null || StringUtils.isBlank(keyProperty)) {
return null;
}
Map<K, V> map = Maps.newHashMap();
if (useGetter) {
for (V item : list) {
Method[] methods = item.getClass().getMethods();
for (Method method : methods) {
String getterName = "get" + keyProperty.toLowerCase();
if (method.getName().toLowerCase().equals(getterName)) {
K key = (K) method.invoke(item);
if (key != null) {
map.put(key, item);
}
break;
}
}
}
} else {
for (V item : list) {
Field[] fields = item.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.getName().equals(keyProperty)) {
K key = (K) field.get(item);
if (key != null) {
map.put(key, item);
}
break;
}
}
}
}
return map;
}
}