package com.constellio.data.utils;
import static com.constellio.data.utils.AccentApostropheCleaner.removeAccents;
import java.util.ArrayList;
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.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
public class LangUtils {
public static <T, V extends T, D extends T> T valueOrDefault(V value, D defaultValue) {
return value != null ? value : defaultValue;
}
public static Comparator<Entry<String, String>> mapStringStringEntryValueComparator() {
return new Comparator<Entry<String, String>>() {
@Override
public int compare(Entry<String, String> o1, Entry<String, String> o2) {
String s1 = removeAccents(o1.getValue());
String s2 = removeAccents(o2.getValue());
return s1.compareTo(s2);
}
};
}
public static LocalDate max(LocalDate date1, LocalDate date2) {
if (date1 == null) {
return date2;
}
if (date2 == null) {
return date1;
}
return date1.isBefore(date2) ? date2 : date1;
}
public static LocalDate min(LocalDate date1, LocalDate date2) {
if (date1 == null) {
return date2;
}
if (date2 == null) {
return date1;
}
return date1.isAfter(date2) ? date2 : date1;
}
public static LocalDateTime max(LocalDateTime date1, LocalDateTime date2) {
if (date1 == null) {
return date2;
}
if (date2 == null) {
return date1;
}
return date1.isBefore(date2) ? date2 : date1;
}
public static LocalDateTime min(LocalDateTime date1, LocalDateTime date2) {
if (date1 == null) {
return date2;
}
if (date2 == null) {
return date1;
}
return date1.isAfter(date2) ? date2 : date1;
}
public static <V> boolean containsAny(Collection<V> firstCollection, Collection<V> secondCollection) {
for (V firstCollectionValue : firstCollection) {
for (V secondCollectionValue : secondCollection) {
if (firstCollectionValue != null && firstCollectionValue.equals(secondCollectionValue)) {
return true;
}
}
}
return false;
}
public static <K, V> Map<K, V> newMapWithEntry(K key, V value) {
Map<K, V> values = new HashMap<>();
values.put(key, value);
return values;
}
public static boolean areNullableEqual(Object o1, Object o2) {
if (o1 == null && o2 == null) {
return true;
} else if (o1 == null && o2 != null) {
return false;
} else if (o1 != null && o2 == null) {
return false;
} else {
return o1.equals(o2);
}
}
public static <K, V> MapComparisonResults<K, V> compare(Map<K, V> before, Map<K, V> after) {
Set<K> keysBefore = before.keySet();
ListComparisonResults<K> results = compare(keysBefore, after.keySet());
List<ModifiedEntry<K, V>> modifiedEntries = new ArrayList<>();
for (K key : keysBefore) {
if (after.containsKey(key)) {
V valueBefore = before.get(key);
V valueAfter = after.get(key);
if (!LangUtils.areNullableEqual(valueBefore, valueAfter)) {
modifiedEntries.add(new ModifiedEntry<>(key, valueBefore, valueAfter));
}
}
}
return new MapComparisonResults<>(results.getNewItems(), results.getRemovedItems(), modifiedEntries);
}
public static <T> ListComparisonResults<T> compare(Set<T> before, Set<T> after) {
return compare(new ArrayList<>(before), new ArrayList<>(after));
}
public static <T> ListComparisonResults<T> compare(List<T> before, List<T> after) {
List<T> newItems = new ArrayList<>();
List<T> removedItems = new ArrayList<>();
if (after == null) {
removedItems = new ArrayList<>(before);
} else if (before == null) {
newItems = new ArrayList<>(after);
} else if (after != null && after != null) {
if (before != null) {
for (T item : before) {
if (!after.contains(item) && !removedItems.contains(item)) {
removedItems.add(item);
}
}
}
if (after != null) {
for (T item : after) {
if (!before.contains(item) && !newItems.contains(item)) {
newItems.add(item);
}
}
}
}
return new ListComparisonResults<>(newItems, removedItems);
}
public static boolean isEqual(Object value1, Object value2) {
if (value1 == null) {
return value2 == null;
} else {
return value1.equals(value2);
}
}
public static void ensureNoNullItems(List<?> items) {
for (Object item : items) {
if (item == null) {
throw new IllegalArgumentException("Null values are not allowed in list");
}
}
}
public static boolean isTrueOrNull(Object value) {
return !Boolean.FALSE.equals(value);
}
public static boolean isFalseOrNull(Object value) {
return !Boolean.TRUE.equals(value);
}
public static <T> List<T> withoutDuplicates(List<T> value) {
return new ArrayList<>(new HashSet<>(value));
}
public static List<String> withoutDuplicatesAndNulls(List<String> value) {
List<String> values = new ArrayList<>(new HashSet<>(value));
values.remove(null);
return values;
}
public static <T> List<T> withoutNulls(List<T> items) {
return (List<T>) withoutNulls((Collection<T>) items);
}
public static <T> Collection<T> withoutNulls(Collection<T> userPermissionsOnRecord) {
List<T> withoutNulls = new ArrayList<>();
Iterator<T> valuesIterator = userPermissionsOnRecord.iterator();
while (valuesIterator.hasNext()) {
T value = valuesIterator.next();
if (value != null) {
withoutNulls.add(value);
}
}
return withoutNulls;
}
public static int compareStrings(String value1, String value2) {
String normalizedValue1 = removeAccents(value1);
String normalizedValue2 = removeAccents(value2);
return normalizedValue1.compareTo(normalizedValue2);
}
public static <T> boolean hasSameElementsNoMatterTheOrder(List<T> list1, List<T> list2) {
Set<T> set1 = new HashSet<>(list1);
Set<T> set2 = new HashSet<>(list2);
return set1.equals(set2);
}
public static int countIteratorValues(Iterator<?> iterator) {
int count = 0;
while (iterator.hasNext()) {
iterator.next();
count++;
}
return count;
}
public static int nullableNaturalCompare(Comparable v1, Comparable v2) {
if (v1 == null) {
if (v2 == null) {
return 0;
} else {
return -1;
}
} else {
if (v2 == null) {
return 1;
} else {
return v1.compareTo(v2);
}
}
}
public static StringReplacer replacingLiteral(String target, String replacement) {
return new StringReplacer().replacingLiteral(target, replacement);
}
public static StringReplacer replacingRegex(String regex, String replacement) {
return new StringReplacer().replacingRegex(regex, replacement);
}
public static class StringReplacer {
List<StringReplacement> stringReplacements = new ArrayList<>();
public StringReplacer replacingRegex(String regex, String replacement) {
Pattern pattern = Pattern.compile(regex);
stringReplacements.add(new StringReplacement(pattern, replacement));
return this;
}
public StringReplacer replacingLiteral(String target, String replacement) {
if (!target.equals(replacement)) {
Pattern pattern = Pattern.compile(target.toString(), Pattern.LITERAL);
stringReplacements.add(new StringReplacement(pattern, replacement));
}
return this;
}
public String replaceOn(String value) {
String output = value;
for (StringReplacement stringReplacement : stringReplacements) {
output = stringReplacement.replace(output);
}
return output;
}
}
public static class StringReplacement {
Pattern pattern;
CharSequence replacement;
public StringReplacement(Pattern pattern, CharSequence replacement) {
this.pattern = pattern;
this.replacement = replacement;
}
String replace(String value) {
return pattern.matcher(value).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
}
public static class ListComparisonResults<T> {
private List<T> newItems;
private List<T> removedItems;
public ListComparisonResults(List<T> newItems, List<T> removedItems) {
this.newItems = Collections.unmodifiableList(newItems);
this.removedItems = Collections.unmodifiableList(removedItems);
}
public List<T> getNewItems() {
return newItems;
}
public List<T> getRemovedItems() {
return removedItems;
}
}
public static class MapComparisonResults<K, V> {
private List<K> newEntries;
private List<K> removedEntries;
private List<ModifiedEntry<K, V>> modifiedEntries;
public MapComparisonResults(List<K> newEntries, List<K> removedEntries,
List<ModifiedEntry<K, V>> modifiedEntries) {
this.newEntries = Collections.unmodifiableList(newEntries);
this.removedEntries = Collections.unmodifiableList(removedEntries);
this.modifiedEntries = Collections.unmodifiableList(modifiedEntries);
}
public List<K> getNewEntries() {
return newEntries;
}
public List<K> getRemovedEntries() {
return removedEntries;
}
public List<ModifiedEntry<K, V>> getModifiedEntries() {
return modifiedEntries;
}
}
public static class ModifiedEntry<K, V> {
private K key;
private V valueBefore;
private V valueAfter;
public ModifiedEntry(K key, V valueBefore, V valueAfter) {
this.key = key;
this.valueBefore = valueBefore;
this.valueAfter = valueAfter;
}
public K getKey() {
return key;
}
public V getValueBefore() {
return valueBefore;
}
public V getValueAfter() {
return valueAfter;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
}
public static String tabs(int n) {
return repeat("\t", n);
}
public static String repeat(String string, int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(string);
}
return sb.toString();
}
public static Map<String, String> asMap(String key1, String value1) {
Map<String, String> parameters = new HashMap<>();
parameters.put(key1, value1);
return parameters;
}
public static Map<String, String> asMap(String key1, String value1, String key2, String value2) {
Map<String, String> parameters = new HashMap<>();
parameters.put(key1, value1);
parameters.put(key2, value2);
return parameters;
}
public static Map<String, String> asMap(String key1, String value1, String key2, String value2, String key3, String value3) {
Map<String, String> parameters = new HashMap<>();
parameters.put(key1, value1);
parameters.put(key2, value2);
parameters.put(key3, value3);
return parameters;
}
public static <V> Iterator<V> synchronizedIterator(final Iterator<V> nestedIterator) {
return new Iterator<V>() {
@Override
public synchronized boolean hasNext() {
return nestedIterator.hasNext();
}
@Override
public synchronized V next() {
return nestedIterator.next();
}
@Override
public synchronized void remove() {
nestedIterator.remove();
}
};
}
}