package org.hibernate.validator.internal.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
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.concurrent.ConcurrentHashMap;
public final class CollectionHelper {
private CollectionHelper() {
}
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K, V>();
}
public static <K, V> HashMap<K, V> newHashMap(int size) {
return new HashMap<K, V>( getInitialCapacityFromExpectedSize( size ) );
}
public static <K, V> HashMap<K, V> newHashMap(Map<K, V> map) {
return new HashMap<K, V>( map );
}
public static <K, V> ConcurrentHashMap<K, V> newConcurrentHashMap() {
return new ConcurrentHashMap<K, V>();
}
public static <T> HashSet<T> newHashSet() {
return new HashSet<T>();
}
public static <T> HashSet<T> newHashSet(int size) {
return new HashSet<T>( getInitialCapacityFromExpectedSize( size ) );
}
public static <T> HashSet<T> newHashSet(Collection<? extends T> c) {
return new HashSet<T>( c );
}
public static <T> HashSet<T> newHashSet(Iterable<? extends T> iterable) {
HashSet<T> set = newHashSet();
for ( T t : iterable ) {
set.add( t );
}
return set;
}
public static <T> ArrayList<T> newArrayList() {
return new ArrayList<T>();
}
public static <T> ArrayList<T> newArrayList(int size) {
return new ArrayList<T>( size );
}
@SafeVarargs
public static <T> ArrayList<T> newArrayList(Iterable<T>... iterables) {
ArrayList<T> resultList = newArrayList();
for ( Iterable<T> oneIterable : iterables ) {
for ( T oneElement : oneIterable ) {
resultList.add( oneElement );
}
}
return resultList;
}
@SafeVarargs
public static <T> Set<T> asSet(T... ts) {
return new HashSet<>( Arrays.asList( ts ) );
}
public static <T> List<T> toImmutableList(List<? extends T> list) {
switch ( list.size() ) {
case 0:
return Collections.emptyList();
case 1:
return Collections.singletonList( list.get( 0 ) );
default:
return Collections.unmodifiableList( list );
}
}
public static <T> Set<T> toImmutableSet(Set<? extends T> set) {
switch ( set.size() ) {
case 0:
return Collections.emptySet();
case 1:
return Collections.singleton( set.iterator().next() );
default:
return Collections.unmodifiableSet( set );
}
}
public static <K, V> Map<K, V> toImmutableMap(Map<K, V> map) {
switch ( map.size() ) {
case 0:
return Collections.emptyMap();
case 1:
Entry<K, V> entry = map.entrySet().iterator().next();
return Collections.singletonMap( entry.getKey(), entry.getValue() );
default:
return Collections.unmodifiableMap( map );
}
}
private static int getInitialCapacityFromExpectedSize(int expectedSize) {
if ( expectedSize < 3 ) {
return expectedSize + 1;
}
return (int) ( (float) expectedSize / 0.75f + 1.0f );
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Iterator<?> iteratorFromArray(Object object) {
return new ArrayIterator( accessorFromArray( object ), object );
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Iterable<?> iterableFromArray(Object object) {
return new ArrayIterable( accessorFromArray( object ), object );
}
private static ArrayAccessor<?, ?> accessorFromArray(Object object) {
ArrayAccessor<?, ?> accessor;
if ( Object.class.isAssignableFrom( object.getClass().getComponentType() ) ) {
accessor = ArrayAccessor.OBJECT;
}
else if ( object.getClass() == boolean[].class ) {
accessor = ArrayAccessor.BOOLEAN;
}
else if ( object.getClass() == int[].class ) {
accessor = ArrayAccessor.INT;
}
else if ( object.getClass() == long[].class ) {
accessor = ArrayAccessor.LONG;
}
else if ( object.getClass() == double[].class ) {
accessor = ArrayAccessor.DOUBLE;
}
else if ( object.getClass() == float[].class ) {
accessor = ArrayAccessor.FLOAT;
}
else if ( object.getClass() == byte[].class ) {
accessor = ArrayAccessor.BYTE;
}
else if ( object.getClass() == short[].class ) {
accessor = ArrayAccessor.SHORT;
}
else if ( object.getClass() == char[].class ) {
accessor = ArrayAccessor.CHAR;
}
else {
throw new IllegalArgumentException( "Provided object " + object + " is not a supported array type" );
}
return accessor;
}
private static class ArrayIterable<A, T> implements Iterable<T> {
private final ArrayAccessor<A, T> accessor;
private final A values;
public ArrayIterable(ArrayAccessor<A, T> accessor, A values) {
this.accessor = accessor;
this.values = values;
}
@Override
public final Iterator<T> iterator() {
return new ArrayIterator<>( accessor, values );
}
}
private static class ArrayIterator<A, T> implements Iterator<T> {
private final ArrayAccessor<A, T> accessor;
private final A values;
private int current = 0;
public ArrayIterator(ArrayAccessor<A, T> accessor, A values) {
this.accessor = accessor;
this.values = values;
}
@Override
public boolean hasNext() {
return current < accessor.size( values );
}
@Override
public T next() {
T result = accessor.get( values, current );
current++;
return result;
}
}
private interface ArrayAccessor<A, T> {
int size(A array);
T get(A array, int index);
ArrayAccessor<Object[], Object> OBJECT = new ArrayAccessor<Object[], Object>() {
@Override
public int size(Object[] array) {
return array.length;
}
@Override
public Object get(Object[] array, int index) {
return array[index];
}
};
ArrayAccessor<boolean[], Boolean> BOOLEAN = new ArrayAccessor<boolean[], Boolean>() {
@Override
public int size(boolean[] array) {
return array.length;
}
@Override
public Boolean get(boolean[] array, int index) {
return array[index];
}
};
ArrayAccessor<int[], Integer> INT = new ArrayAccessor<int[], Integer>() {
@Override
public int size(int[] array) {
return array.length;
}
@Override
public Integer get(int[] array, int index) {
return array[index];
}
};
ArrayAccessor<long[], Long> LONG = new ArrayAccessor<long[], Long>() {
@Override
public int size(long[] array) {
return array.length;
}
@Override
public Long get(long[] array, int index) {
return array[index];
}
};
ArrayAccessor<double[], Double> DOUBLE = new ArrayAccessor<double[], Double>() {
@Override
public int size(double[] array) {
return array.length;
}
@Override
public Double get(double[] array, int index) {
return array[index];
}
};
ArrayAccessor<float[], Float> FLOAT = new ArrayAccessor<float[], Float>() {
@Override
public int size(float[] array) {
return array.length;
}
@Override
public Float get(float[] array, int index) {
return array[index];
}
};
ArrayAccessor<byte[], Byte> BYTE = new ArrayAccessor<byte[], Byte>() {
@Override
public int size(byte[] array) {
return array.length;
}
@Override
public Byte get(byte[] array, int index) {
return array[index];
}
};
ArrayAccessor<short[], Short> SHORT = new ArrayAccessor<short[], Short>() {
@Override
public int size(short[] array) {
return array.length;
}
@Override
public Short get(short[] array, int index) {
return array[index];
}
};
ArrayAccessor<char[], Character> CHAR = new ArrayAccessor<char[], Character>() {
@Override
public int size(char[] array) {
return array.length;
}
@Override
public Character get(char[] array, int index) {
return array[index];
}
};
}
}