/* * Copyright 2015 Evgeny Dolganov (evgenij.dolganov@gmail.com). * * Licensed 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 och.util; import static java.util.Collections.*; import static och.util.json.GsonUtil.*; import static och.util.log.LogUtil.*; import java.lang.reflect.Array; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.locks.Lock; import och.util.exception.BreakLoopException; import och.util.exception.ContinueLoopException; import och.util.model.CallableVoid; import och.util.model.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Util { public static final String UTF8 = "UTF8"; public static Log getLog(Class<?> clazz){ return getAsyncLogIfNeed(LogFactory.getLog(clazz)); } public static Log getLog(String name){ return getAsyncLogIfNeed(LogFactory.getLog(name)); } public static boolean equalsOrNull(Object a, Object b){ if(a == null && b == null) return true; if(a != null && a.equals(b)) return true; return false; } public static boolean isEmpty(Object o) { return o == null; } public static boolean isEmpty(Collection<?> col) { return col == null || col.size() == 0; } public static boolean isEmpty(String str) { return str == null || str.length() == 0; } public static boolean isEmpty(Map<?, ?> map) { return map == null || map.size() == 0; } public static boolean isEmpty(Object[] arr) { return arr == null || arr.length == 0; } public static boolean hasText(String str) { if (!hasLength(str)) { return false; } int strLen = str.length(); for (int i = 0; i < strLen; i++) { if (!Character.isWhitespace(str.charAt(i))) { return true; } } return false; } public static boolean hasLength(String str) { return (str != null && str.length() > 0); } @SafeVarargs public static <T> ArrayList<T> list(T... elems) { if(elems == null){ return null; } ArrayList<T> list = new ArrayList<T>(elems.length); for (T elem : elems) { list.add(elem); } return list; } @SuppressWarnings({ "unchecked", "rawtypes" }) public static <T> T[] array(Collection collection, Class<T> type){ if(collection == null){ return null; } T[] array = (T[])Array.newInstance(type, collection.size()); return (T[])collection.toArray(array); } public static <T> ArrayList<T> toList(Collection<T> collection) { if (collection == null) { return null; } ArrayList<T> out = null; if (collection instanceof ArrayList<?>) { out = (ArrayList<T>) collection; } else { out = new ArrayList<T>(collection); } return out; } public static <T> ArrayList<T> toList(Enumeration<T> enumeration) { if (enumeration == null) { return null; } ArrayList<T> out = new ArrayList<>(); while(enumeration.hasMoreElements()){ out.add(enumeration.nextElement()); } return out; } public static <T> List<T> subList(List<T> list, int fromIndex){ if(isEmpty(list)) return list; if(fromIndex < 0) fromIndex = 0; int size = list.size(); if(fromIndex >= size) return emptyList(); return list.subList(fromIndex, size); } public static <K, V> HashMap<K, V> map(){ return new HashMap<K, V>(); } public static <K, V> HashMap<K, V> map(K key, V val){ HashMap<K, V> out = new HashMap<>(); out.put(key, val); return out; } public static <K, V> HashMap<K, V> map(K key1, V val1, K key2, V val2){ HashMap<K, V> out = new HashMap<>(); out.put(key1, val1); out.put(key2, val2); return out; } public static <K, V> HashMap<K, V> map(K key1, V val1, K key2, V val2, K key3, V val3){ HashMap<K, V> out = new HashMap<>(); out.put(key1, val1); out.put(key2, val2); out.put(key3, val3); return out; } @SafeVarargs public static <V> HashSet<V> set(V... vals){ HashSet<V> out = new HashSet<>(); for (V val : vals) { out.add(val); } return out; } public static Integer tryParseInt(Object obj, Integer defaultVal){ if(obj == null) return defaultVal; if(obj instanceof Integer) return (Integer) obj; try { String val = obj.toString(); return Integer.parseInt(val); }catch (Exception e) { return defaultVal; } } public static Long tryParseLong(Object obj, Long defaultVal){ if(obj == null) return defaultVal; if(obj instanceof Long) return (Long) obj; try { String val = obj.toString(); return Long.parseLong(val); }catch (Exception e) { return defaultVal; } } public static Double tryParseDouble(Object obj, Double defaultVal){ if(obj == null) return defaultVal; if(obj instanceof Double) return (Double) obj; try { String val = obj.toString(); return Double.parseDouble(val); }catch (Exception e) { return defaultVal; } } public static Boolean tryParseBool(Object obj, Boolean defaultVal){ if(obj == null) return defaultVal; if(obj instanceof Boolean) return (Boolean) obj; try { String val = obj.toString(); return Boolean.parseBoolean(val); }catch (Exception e) { return defaultVal; } } public static <T extends Enum<T>> T tryParseEnum(Object ob, Class<T> enumType){ return tryParseEnum(ob, enumType, null); } public static <T extends Enum<T>> T tryParseEnum(Object ob, Class<T> enumType, T defaultVal){ if(ob == null) return defaultVal; try { return (T)Enum.valueOf(enumType, String.valueOf(ob)); }catch (Exception e) { return defaultVal; } } public static <T extends Enum<T>> T tryGetEnumByCode(Integer code, Class<T> enumType, T defaultVal){ if(code == null) return defaultVal; try { for (T c : enumType.getEnumConstants()) { int curCode = ((och.util.model.HasIntCode)c).getCode(); if(curCode == code)return c; } return defaultVal; }catch (Exception e) { return defaultVal; } } public static Date tryParseDate(String date, String format, Date defaultDate){ return DateUtil.tryParseDate(date, format, defaultDate); } public static BigDecimal tryParseBigDecimal(String val, BigDecimal defaultVal){ if(val == null) return defaultVal; try { return new BigDecimal(val); }catch (Exception e) { return defaultVal; } } public static String toJson(Object ob){ return toJson(ob, false); } public static String toJson(Object ob, boolean prettyPrinting){ return ! prettyPrinting ? defaultGson.toJson(ob) : defaultGsonPrettyPrinting.toJson(ob); } public static <T> T tryParseJson(String val, Class<T> type){ return tryParseJson(val, type, null); } public static <T> T tryParseJson(String val, Class<T> type, T defObj){ if(val == null) return defObj; try { return defaultGson.fromJson(val, type); }catch (Exception e) { return defObj; } } public static String toObjectString(Object ob) { return ob.getClass().getName() + "@" + Integer.toHexString(ob.hashCode()); } public static void checkArgumentForEmpty(Object ob, String argMsg) throws IllegalArgumentException { if (isEmpty(ob)) throw new IllegalArgumentException("arg is empty: "+argMsg); } public static void checkArgument(boolean state, String errorMsg) throws IllegalStateException { if (!state) throw new IllegalArgumentException(errorMsg); } public static void checkState(boolean state, String errorMsg) throws IllegalStateException { if (!state) throw new IllegalStateException(errorMsg); } public static void checkStateForEmpty(Object ob, String argMsg) throws IllegalStateException { if (isEmpty(ob)) throw new IllegalStateException("arg is empty: "+argMsg); } public static String randomUUID() { UUID uuid = UUID.randomUUID(); String out = uuid.toString(); return out.toString(); } public static String randomSimpleId(){ return System.currentTimeMillis()+"-"+System.nanoTime(); } public static boolean[] array(boolean... elems) { return elems; } public static int compareTo(long a, long b) { return (a<b ? -1 : (a==b ? 0 : 1)); } public static int compareTo(int a, int b) { return (a<b ? -1 : (a==b ? 0 : 1)); } public static String getDeltaTime(long start) { long stop = System.currentTimeMillis(); long delta = Math.abs(stop - start); String deltaStr = delta>1000 ? ""+(delta/1000.)+"sec" : ""+delta+"ms"; return deltaStr; } public static void assertHasText(String str){ if(!hasText(str)) throw new IllegalArgumentException("no text in str"); } public static interface ItemConverter<I, O> { O covert(I item) throws ContinueLoopException, BreakLoopException; } public static <I, O> List<O> convert(Collection<I> coll, ItemConverter<I, O> itemConverter){ if(isEmpty(coll)) return list(); ArrayList<O> out = new ArrayList<>(coll.size()); for (I obj : coll){ try { O item = itemConverter.covert(obj); out.add(item); }catch(ContinueLoopException e){ continue; }catch (BreakLoopException e) { break; } } return out; } public static interface FindPredicat<I> { boolean isValid(I item) throws BreakLoopException; } public static <I> I find(Collection<I> coll, FindPredicat<I> predicat){ if(isEmpty(coll)) return null; for (I item : coll){ try { if(predicat.isValid(item)) return item; }catch (BreakLoopException e) { break; } } return null; } public static <I, K, V> Map<K, V> toMap(Collection<I> coll, ItemConverter<I, Pair<K, V>> converter){ if(isEmpty(coll)) return map(); HashMap<K, V> out = new HashMap<>(); for (I val : coll){ Pair<K, V> pair = converter.covert(val); out.put(pair.first, pair.second); } return out; } @SuppressWarnings({ "unchecked", "rawtypes" }) public static void putToListMap(Map mapOfLists, Object key, Object val) { List list = (List<?>)mapOfLists.get(key); if(list == null){ list = new ArrayList<>(); mapOfLists.put(key, list); } list.add(val); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static void putToSetMap(Map mapOfSets, Object key, Object val) { Set set = (Set<?>)mapOfSets.get(key); if(set == null){ set = new HashSet<>(); mapOfSets.put(key, set); } set.add(val); } public static <T> T lastFrom(List<T> list){ return list.get(list.size()-1); } public static <T> T firstFrom(Collection<T> coll){ if(isEmpty(coll)) return null; return coll.iterator().next(); } public static <T> T inLock(Lock lock, Callable<T> body) throws Exception{ lock.lock(); try { return body.call(); }finally { lock.unlock(); } } public static void inLock(Lock lock, CallableVoid body) throws Exception{ lock.lock(); try { body.call(); }finally { lock.unlock(); } } public static interface DuplicateProvider<T> { boolean isDuplicates(T a, T b); int findBestFrom(List<T> duplicates); } /** * пример: * <br> * дубликаты по равенству без учета заглавной буквы, лучше те, что заглавной: * <br> * ["a", "a", "b", "A", "c", "B"] -> ["A", "B", "c"] */ public static <T> List<T> filterByBestFromDuplicates(List<T> list, DuplicateProvider<T> provider){ if(isEmpty(list)) return list; ArrayList<T> filtered = new ArrayList<>(); HashSet<Integer> processedIndexes = new HashSet<>(); int size = list.size(); for (int i = 0; i < size; i++) { //уже был обработан ранее if(processedIndexes.contains(i)) continue; T cur = list.get(i); ArrayList<T> duplicates = null; //Ищем дубликаты for (int j = i+1; j < size; j++) { T other = list.get(j); //нашли дубликат - заносим его в список дубликтов, помечаем глобально обработанным if (provider.isDuplicates(cur, other)) { if(duplicates == null) duplicates = new ArrayList<>(); duplicates.add(other); processedIndexes.add(j); } } //похожих не найдено - точно валидный if(duplicates == null){ filtered.add(cur); continue; } //получаем финальный список дубликатов duplicates.add(0, cur); //ищем среди них лучший int bestIndex = provider.findBestFrom(new ArrayList<>(duplicates)); if(bestIndex == -1 || bestIndex > duplicates.size() - 1) continue; T best = duplicates.get(bestIndex); filtered.add(best); } return filtered; } public static boolean isUpdateNotEmptyVal(String oldVal, String newVal){ if( oldVal == null) return newVal != null; return hasText(newVal) && ! oldVal.equals(newVal); } }