package pl.net.bluesoft.util.lang;
import org.apache.commons.beanutils.PropertyUtils;
import pl.net.bluesoft.util.lang.exception.UtilityInvocationException;
import java.lang.reflect.Field;
import java.util.*;
public final class Lang {
private Lang() {}
public static final FilterOut NORESULT = new FilterOut();
private static class FilterOut {
}
private static final class Unpack {
private List list;
private Unpack(List list) {
this.list = list;
}
public List getList() {
return list;
}
}
public static Unpack unpack(List list) {
return new Unpack(list);
}
public static <T1, T2> List mapcar(Collection<T1> list, Lambda<T1, T2> func) {
ArrayList<T2> ret = new ArrayList<T2>();
if (list == null) {
return ret;
}
for (T1 obj : list) {
Object res = func.lambda(obj);
if(res.equals(NORESULT)) {
continue;
}
if(res instanceof Unpack) {
ret.addAll(((Unpack) res).getList());
}
else {
ret.add(func.lambda(obj));
}
}
return ret;
}
public static<T1, T2> List mapcar(Object[] list, Lambda<T1, T2> func) {
return mapcar((Collection)Arrays.asList(list), func);
}
//throw runtimeexception or return empty list?
public static <T1, T2> List<T2> keyFilter(final String s, Collection<T1> list) {
return mapcar(list, new Lambda<T1, T2>() {
public T2 lambda(T1 val) {
try {
return (T2) PropertyUtils.getProperty(val, s);
} catch (Exception e) { throw new UtilityInvocationException(e.getMessage(), e); }
}
});
}
//throw runtimeexception or return empty list?
public static <T1, T2> T2 reduce(List<T1> list, Lambda<T1, T2> func, T2 init) {
if (list == null || list.size() <= 0) {
return init;
}
return reduce(list.subList(1, list.size()), func, func.lambda(init, list.get(0)));
}
//throw runtimeexception or return empty list?
public static List keyFilterReduce(final String key, List list) {
return (List) reduce(keyFilter(key, list), new Lambda() {
public Object lambda(Object val1, Object val2) {
try {
((Collection)val1).addAll((Collection) val2);
return val1;
} catch (Exception e) { throw new UtilityInvocationException(e.getMessage(), e); }
}
}, new ArrayList());
}
public static <T1, T2> List<T2> filterValues(Map<T1, T2> map, T1... keys) {
List<T2> ret = new ArrayList();
Set goodKeys = new HashSet(Arrays.asList(keys));
for(T1 key : keys) {
if(goodKeys.contains(key)) {
ret.add(map.get(key));
}
}
return ret;
}
public static <T1, T2> T2 coalesce(Map<T1, T2> map, T1... keys) {
return reduce(filterValues(map, keys), new Lambda<T2, T2>() {
public T2 lambda(T2 val1, T2 val2) {
return val1 == null ? val2 : val1;
}
}, null);
}
private static class PropertyException extends RuntimeException { PropertyException(Throwable e) {super(e);}};
public static void set(Object o, String propertyName, Object value) {
try {
PropertyUtils.setProperty(o, propertyName, value);
} catch (Exception e) { throw new PropertyException(e); }
}
public static Object get(Object o, String propertyName) {
try {
return PropertyUtils.getProperty(o, propertyName);
} catch (Exception e) { throw new PropertyException(e); }
}
public static Field[] getFieldsFromClassAndAncestors(Class clazz) {
List<Field> fields = new LinkedList<Field>(Arrays.asList(clazz.getDeclaredFields()));
if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) {
fields.addAll(Arrays.asList(getFieldsFromClassAndAncestors(clazz.getSuperclass())));
}
return fields.toArray(new Field[fields.size()]);
}
public static Object[] array(Object...vals) {
return mapcar(vals, new Lambda<Object, Object>() {
public Object lambda(Object val) {
return val;
}
}).toArray();
}
public static List list(Object...vals) {
return mapcar(vals, new Lambda<Object, Object>() {
public Object lambda(Object val) {
return val;
}
});
}
public static boolean isNumber(String str) {
try {
Integer.parseInt(str);
}
catch (NumberFormatException e) {
return false;
}
return true;
}
public static <T1, T2> boolean equals(T1 t1, T2 t2) {
return t1 == t2 || t1 != null && t1.equals(t2);
}
public static <T extends Comparable<T>> int compare(T x, T y) {
if (x == y) {
return 0;
}
if (x == null) {
return +1;
}
if (y == null) {
return -1;
}
return +x.compareTo(y);
}
public static <T> int compare(T[] x, T[] y) {
int len = Math.min(x.length, y.length);
for (int i = 0; i < len; ++i) {
int cmp = compare((Comparable)x[i], (Comparable)y[i]);
if (cmp != 0) {
return cmp;
}
}
return x.length - y.length;
}
public static <T extends Comparable<T>> T keepInRange(T value, T from, T to) {
if (value == null) {
return null;
}
if (from != null && value.compareTo(from) < 0) {
value = from;
}
if (to != null && value.compareTo(to) > 0) {
value = to;
}
return value;
}
}