package com.ldbc.driver.util;
import com.google.common.collect.Lists;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
public class MapUtils
{
public static <K, V> String prettyPrint( Map<K,V> map )
{
return prettyPrint( map, "" );
}
public static <K, V> String prettyPrint( Map<K,V> map, String prefix )
{
List<Entry<K,V>> mapEntries = sortedEntrySet( map );
StringBuilder sb = new StringBuilder();
for ( Entry<K,V> entry : mapEntries )
{
String keyString = (null == entry.getKey()) ? "null" : entry.getKey().toString();
String valueString = (null == entry.getValue()) ? "null" : entry.getValue().toString();
sb.append( prefix ).append( keyString ).append( " = " ).append( valueString ).append( "\n" );
}
return sb.toString();
}
public static <K, V> List<Entry<K,V>> sortedEntrySet( Map<K,V> map )
{
return sortedEntries( map.entrySet() );
}
public static <K, V> List<Entry<K,V>> sortedEntries( Iterable<Entry<K,V>> entries )
{
List<Entry<K,V>> sortedEntries = Lists.newArrayList( entries );
Collections.sort( sortedEntries, new EntriesComparator<K>() );
return sortedEntries;
}
private static class EntriesComparator<K> implements Comparator<Entry<K,?>>
{
@Override
public int compare( Entry<K,?> o1, Entry<K,?> o2 )
{
if ( o1.getKey() instanceof Comparable )
{ return ((Comparable) o1.getKey()).compareTo( o2.getKey() ); }
else
{ return o1.toString().compareTo( o2.toString() ); }
}
}
/**
* Returns new Map
*
* @param map
* @param excludedKeys
* @return
*/
public static <K, V> Map<K,V> copyExcludingKeys( Map<K,V> map, Set<K> excludedKeys )
{
Map<K,V> resultMap = new HashMap<>();
for ( Entry<K,V> entry : map.entrySet() )
{
if ( false == excludedKeys.contains( entry.getKey() ) )
{ resultMap.put( entry.getKey(), entry.getValue() ); }
}
return resultMap;
}
public static <K, V> V getDefault( Map<K,V> map, K key, V defaultValue )
{
return (map.containsKey( key )) ? map.get( key ) : defaultValue;
}
public static <K, V> Map<K,V> propertiesToMap( Properties properties )
{
Map<K,V> resultMap = new HashMap<>();
for ( Object propertyKey : properties.keySet() )
{
resultMap.put( (K) propertyKey, (V) properties.get( (K) propertyKey ) );
}
return resultMap;
}
/**
* Returns new Map
*
* @param properties
* @param map
* @param overwrite
* @return
*/
public static <K, V> Map<K,V> mergePropertiesToMap( Properties properties, Map<K,V> map, boolean overwrite )
{
Map<K,V> resultMap = new HashMap<>();
for ( K mapKey : map.keySet() )
{
resultMap.put( mapKey, map.get( mapKey ) );
}
for ( Object propertyKey : properties.keySet() )
{
if ( (overwrite) || (false == resultMap.containsKey( (K) propertyKey )) )
{
resultMap.put( (K) propertyKey, (V) properties.get( (K) propertyKey ) );
}
}
return resultMap;
}
/**
* Converts Map to Properties
*
* @param map
* @return
*/
public static <K, V> Properties mapToProperties( Map<K,V> map )
{
return mergeMapToProperties( map, new Properties(), true );
}
/**
* Returns new Properties
*
* @param map
* @param properties
* @param overwrite
* @return
*/
public static <K, V> Properties mergeMapToProperties( Map<K,V> map, Properties properties, boolean overwrite )
{
Properties resultProperties = new Properties();
for ( Object propertyKey : properties.keySet() )
{
resultProperties.put( propertyKey, properties.get( propertyKey ) );
}
for ( K mapKey : map.keySet() )
{
if ( (overwrite) || (false == resultProperties.containsKey( mapKey )) )
{
resultProperties.put( mapKey, map.get( mapKey ) );
}
}
return resultProperties;
}
/**
* newMap value overwrites originalMap value if they share a common key
*
* @param originalMap
* @param newMap
* @param overwrite
* @param <K>
* @param <V>
* @return
*/
public static <K, V> Map<K,V> mergeMaps(
Map<K,V> originalMap,
Map<K,V> newMap,
final boolean overwrite )
{
Function2<V,V,V,RuntimeException> overwriteFun = new Function2<V,V,V,RuntimeException>()
{
@Override
public V apply( V originalVal, V newVal )
{
return (overwrite) ? newVal : originalVal;
}
};
return mergeMaps( originalMap, newMap, overwriteFun );
}
/**
* mergeFun only called for keys that exist in both Map instances
*
* @param originalMap
* @param newMap
* @param mergeFun
* @return
*/
public static <K, V> Map<K,V> mergeMaps(
Map<K,V> originalMap,
Map<K,V> newMap,
Function2<V,V,V,RuntimeException> mergeFun )
{
Map<K,V> resultMap = new HashMap<>();
for ( K originalMapKey : originalMap.keySet() )
{
resultMap.put( originalMapKey, originalMap.get( originalMapKey ) );
}
for ( K newMapKey : newMap.keySet() )
{
if ( resultMap.containsKey( newMapKey ) )
{
resultMap.put( newMapKey, mergeFun.apply( originalMap.get( newMapKey ), newMap.get( newMapKey ) ) );
}
else
{
resultMap.put( newMapKey, newMap.get( newMapKey ) );
}
}
return resultMap;
}
public static Map<String,String> loadPropertiesToMap( File propertiesFile ) throws IOException
{
InputStream propertiesInputStream = new FileInputStream( propertiesFile );
return loadPropertiesInputStreamToMap( propertiesInputStream );
}
public static Map<String,String> loadPropertiesStringToMap( String propertiesString ) throws IOException
{
InputStream propertiesInputStream =
new ByteArrayInputStream( propertiesString.getBytes( StandardCharsets.UTF_8 ) );
return loadPropertiesInputStreamToMap( propertiesInputStream );
}
public static Map<String,String> loadPropertiesInputStreamToMap( InputStream propertiesInputStream )
throws IOException
{
Properties properties = new Properties();
properties.load( propertiesInputStream );
return propertiesToMap( properties );
}
public static <NEW_KEY_TYPE, OLD_KEY_TYPE, NEW_VALUE_TYPE, OLD_VALUE_TYPE>
Map<NEW_KEY_TYPE,NEW_VALUE_TYPE> UNSAFE_changeTypes(
Map<OLD_KEY_TYPE,OLD_VALUE_TYPE> originalMap,
TypeChangeFun<OLD_KEY_TYPE,NEW_KEY_TYPE> keyFun,
TypeChangeFun<OLD_VALUE_TYPE,NEW_VALUE_TYPE> valueFun
)
{
Map<NEW_KEY_TYPE,NEW_VALUE_TYPE> newMap = new HashMap<>();
for ( OLD_KEY_TYPE oldKey : originalMap.keySet() )
{
newMap.put( keyFun.apply( oldKey ), valueFun.apply( originalMap.get( oldKey ) ) );
}
return newMap;
}
public static <K, V> Map<V,K> UNSAFE_switchKeysAndValues( Map<K,V> originalMap )
{
Map<V,K> newMap = new HashMap<>();
for ( Entry<K,V> entry : originalMap.entrySet() )
{
newMap.put( entry.getValue(), entry.getKey() );
}
return newMap;
}
}