|  | /* | 
|  | * Licensed to the Apache Software Foundation (ASF) under one or more | 
|  | * contributor license agreements.  See the NOTICE file distributed with | 
|  | * this work for additional information regarding copyright ownership. | 
|  | * The ASF licenses this file to You 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 org.apache.usergrid.utils; | 
|  |  | 
|  |  | 
|  | import java.util.ArrayList; | 
|  | import java.util.HashMap; | 
|  | import java.util.LinkedHashMap; | 
|  | import java.util.LinkedHashSet; | 
|  | import java.util.List; | 
|  | import java.util.Map; | 
|  | import java.util.Map.Entry; | 
|  | import java.util.Properties; | 
|  | import java.util.Set; | 
|  | import java.util.TreeMap; | 
|  | import java.util.TreeSet; | 
|  |  | 
|  | import static org.apache.commons.lang.StringUtils.isNotBlank; | 
|  |  | 
|  | import static org.apache.usergrid.utils.ClassUtils.cast; | 
|  |  | 
|  |  | 
|  | public class MapUtils extends org.apache.commons.collections.MapUtils { | 
|  |  | 
|  | public static <A, B> void addMapSet( Map<A, Set<B>> map, A a, B b ) { | 
|  | addMapSet( map, false, a, b ); | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static <A, B> void addMapSet( Map<A, Set<B>> map, boolean ignoreCase, A a, B b ) { | 
|  |  | 
|  | Set<B> setB = map.get( a ); | 
|  | if ( setB == null ) { | 
|  | if ( ignoreCase && ( b instanceof String ) ) { | 
|  | setB = ( Set<B> ) new TreeSet<String>( String.CASE_INSENSITIVE_ORDER ); | 
|  | } | 
|  | else { | 
|  | setB = new LinkedHashSet<B>(); | 
|  | } | 
|  | map.put( a, setB ); | 
|  | } | 
|  | setB.add( b ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <A, B, C> void addMapMapSet( Map<A, Map<B, Set<C>>> map, A a, B b, C c ) { | 
|  | addMapMapSet( map, false, a, b, c ); | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static <A, B, C> void addMapMapSet( Map<A, Map<B, Set<C>>> map, boolean ignoreCase, A a, B b, C c ) { | 
|  |  | 
|  | Map<B, Set<C>> mapB = map.get( a ); | 
|  | if ( mapB == null ) { | 
|  | if ( ignoreCase && ( b instanceof String ) ) { | 
|  | mapB = ( Map<B, Set<C>> ) new TreeMap<String, Set<C>>( String.CASE_INSENSITIVE_ORDER ); | 
|  | } | 
|  | else { | 
|  | mapB = new LinkedHashMap<B, Set<C>>(); | 
|  | } | 
|  | map.put( a, mapB ); | 
|  | } | 
|  | addMapSet( mapB, ignoreCase, b, c ); | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static <A, B, C, D> void addMapMapMapSet( Map<A, Map<B, Map<C, Set<D>>>> map, boolean ignoreCase, A a, B b, | 
|  | C c, D d ) { | 
|  | Map<B, Map<C, Set<D>>> mapB = map.get( a ); | 
|  | if ( mapB == null ) { | 
|  | if ( ignoreCase && ( b instanceof String ) ) { | 
|  | mapB = ( Map<B, Map<C, Set<D>>> ) new TreeMap<String, Map<C, Set<D>>>( String.CASE_INSENSITIVE_ORDER ); | 
|  | } | 
|  | else { | 
|  | mapB = new LinkedHashMap<B, Map<C, Set<D>>>(); | 
|  | } | 
|  | map.put( a, mapB ); | 
|  | } | 
|  | addMapMapSet( mapB, ignoreCase, b, c, d ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <A, B, C> C getMapMap( Map<A, Map<B, C>> map, A a, B b ) { | 
|  |  | 
|  | Map<B, C> mapB = map.get( a ); | 
|  | if ( mapB == null ) { | 
|  | return null; | 
|  | } | 
|  | return mapB.get( b ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <A, B> void addMapList( Map<A, List<B>> map, A a, B b ) { | 
|  |  | 
|  | List<B> listB = map.get( a ); | 
|  | if ( listB == null ) { | 
|  | listB = new ArrayList<B>(); | 
|  | map.put( a, listB ); | 
|  | } | 
|  | listB.add( b ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <A, B> void addListToMapList( Map<A, List<B>> map, A a, List<B> b ) { | 
|  |  | 
|  | List<B> listB = map.get( a ); | 
|  | if ( listB == null ) { | 
|  | listB = new ArrayList<B>(); | 
|  | map.put( a, listB ); | 
|  | } | 
|  | listB.addAll( b ); | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static <K, V> V getValue( Map<K, ?> map, K k ) { | 
|  | V v = null; | 
|  | try { | 
|  | v = ( V ) map.get( k ); | 
|  | } | 
|  | catch ( ClassCastException e ) { | 
|  | //logger.war( "Map value {} was not the expected class", map.get( k ), e ); | 
|  | } | 
|  |  | 
|  | return v; | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static <K, V> Map<?, ?> map( Object... objects ) { | 
|  | Map<K, V> map = new LinkedHashMap<K, V>(); | 
|  | int i = 0; | 
|  | while ( i < objects.length ) { | 
|  | if ( objects[i] instanceof Map.Entry ) { | 
|  | Map.Entry<K, V> entry = ( Entry<K, V> ) objects[i]; | 
|  | map.put( entry.getKey(), entry.getValue() ); | 
|  | i++; | 
|  | } | 
|  | else if ( objects[i] instanceof Map ) { | 
|  | map.putAll( ( Map<? extends K, ? extends V> ) objects[i] ); | 
|  | i++; | 
|  | } | 
|  | else if ( i < ( objects.length - 1 ) ) { | 
|  | K k = ( K ) objects[i]; | 
|  | V v = ( V ) objects[i + 1]; | 
|  | map.put( k, v ); | 
|  | i += 2; | 
|  | } | 
|  | else { | 
|  | break; | 
|  | } | 
|  | } | 
|  | return map; | 
|  | } | 
|  |  | 
|  |  | 
|  | private static class SimpleMapEntry<K, V> implements Map.Entry<K, V> { | 
|  |  | 
|  | private final K k; | 
|  | private V v; | 
|  |  | 
|  |  | 
|  | public SimpleMapEntry( K k, V v ) { | 
|  | this.k = k; | 
|  | this.v = v; | 
|  | } | 
|  |  | 
|  |  | 
|  | @Override | 
|  | public K getKey() { | 
|  | return k; | 
|  | } | 
|  |  | 
|  |  | 
|  | @Override | 
|  | public V getValue() { | 
|  | return v; | 
|  | } | 
|  |  | 
|  |  | 
|  | @Override | 
|  | public V setValue( V v ) { | 
|  | V oldV = this.v; | 
|  | this.v = v; | 
|  | return oldV; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <K, V> Map.Entry<K, V> entry( K k, V v ) { | 
|  | return new SimpleMapEntry<K, V>( k, v ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <K, V> K getFirstKey( Map<K, V> map ) { | 
|  | if ( map == null ) { | 
|  | return null; | 
|  | } | 
|  | Entry<K, V> e = map.entrySet().iterator().next(); | 
|  | if ( e != null ) { | 
|  | return e.getKey(); | 
|  | } | 
|  | return null; | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <V> Map<String, V> filter( Map<String, V> map, String prefix, boolean removePrefix ) { | 
|  | Map<String, V> filteredMap = new LinkedHashMap<String, V>(); | 
|  | for ( Entry<String, V> entry : map.entrySet() ) { | 
|  | if ( entry.getKey().startsWith( prefix ) ) { | 
|  | if ( removePrefix ) { | 
|  | filteredMap.put( entry.getKey().substring( prefix.length() ), entry.getValue() ); | 
|  | } | 
|  | else { | 
|  | filteredMap.put( entry.getKey(), entry.getValue() ); | 
|  | } | 
|  | } | 
|  | } | 
|  | return filteredMap; | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <V> Map<String, V> filter( Map<String, V> map, String prefix ) { | 
|  | return filter( map, prefix, false ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static Properties filter( Properties properties, String prefix, boolean removePrefix ) { | 
|  | Properties filteredProperties = new Properties(); | 
|  | for ( Entry<String, String> entry : asMap( properties ).entrySet() ) { | 
|  | if ( entry.getKey().startsWith( prefix ) ) { | 
|  | if ( removePrefix ) { | 
|  | filteredProperties.put( entry.getKey().substring( prefix.length() ), entry.getValue() ); | 
|  | } | 
|  | else { | 
|  | filteredProperties.put( entry.getKey(), entry.getValue() ); | 
|  | } | 
|  | } | 
|  | } | 
|  | return filteredProperties; | 
|  | } | 
|  |  | 
|  |  | 
|  | public static Properties filter( Properties properties, String prefix ) { | 
|  | return filter( properties, prefix, false ); | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static Map<String, String> asMap( Properties properties ) { | 
|  | return cast( properties ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <S, T> Map<String, Object> toStringObjectMap(Map<S, T> map) { | 
|  | Map<String, Object> newMap = new HashMap<>(); | 
|  | map.forEach((k,v) -> newMap.put(k.toString(), v)); | 
|  | return newMap; | 
|  | } | 
|  |  | 
|  | public static <S, T> HashMapBuilder<S, T> hashMap( S key, T value ) { | 
|  | return new HashMapBuilder<S, T>().map( key, value ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static class HashMapBuilder<S, T> extends HashMap<S, T> { | 
|  | private static final long serialVersionUID = 1L; | 
|  |  | 
|  |  | 
|  | public HashMapBuilder() { | 
|  | } | 
|  |  | 
|  |  | 
|  | public HashMapBuilder<S, T> map( S key, T value ) { | 
|  | put( key, value ); | 
|  | return this; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static Map<String, List<?>> toMapList( Map<String, ?> m ) { | 
|  | Map<String, List<Object>> mapList = new LinkedHashMap<String, List<Object>>(); | 
|  |  | 
|  | for ( Entry<String, ?> e : m.entrySet() ) { | 
|  | if ( e.getValue() instanceof List ) { | 
|  | addListToMapList( mapList, e.getKey(), ( List<Object> ) e.getValue() ); | 
|  | } | 
|  | else { | 
|  | addMapList( mapList, e.getKey(), e.getValue() ); | 
|  | } | 
|  | } | 
|  |  | 
|  | return cast( mapList ); | 
|  | } | 
|  |  | 
|  |  | 
|  | public static Map<String, ?> putPath( String path, Object value ) { | 
|  | return putPath( null, path, value ); | 
|  | } | 
|  |  | 
|  |  | 
|  | @SuppressWarnings("unchecked") | 
|  | public static Map<String, ?> putPath( Map<String, ?> map, String path, Object value ) { | 
|  |  | 
|  | if ( map == null ) { | 
|  | map = new HashMap<String, Object>(); | 
|  | } | 
|  |  | 
|  | int i = path.indexOf( '.' ); | 
|  | if ( i < 0 ) { | 
|  | ( ( Map<String, Object> ) map ).put( path, value ); | 
|  | return map; | 
|  | } | 
|  | String segment = path.substring( 0, i ).trim(); | 
|  | if ( isNotBlank( segment ) ) { | 
|  | Object o = map.get( segment ); | 
|  | if ( ( o != null ) && ( !( o instanceof Map ) ) ) { | 
|  | return map; | 
|  | } | 
|  | Map<String, Object> subMap = ( Map<String, Object> ) o; | 
|  | if ( subMap == null ) { | 
|  | subMap = new HashMap<String, Object>(); | 
|  | ( ( Map<String, Object> ) map ).put( segment, subMap ); | 
|  | } | 
|  | String subPath = path.substring( i + 1 ); | 
|  | if ( isNotBlank( subPath ) ) { | 
|  | putPath( subMap, subPath, value ); | 
|  | } | 
|  | } | 
|  |  | 
|  | return map; | 
|  | } | 
|  |  | 
|  |  | 
|  | public static <K, V> Map<K, V> emptyMapWithKeys( Map<K, V> map ) { | 
|  | Map<K, V> newMap = new HashMap<K, V>(); | 
|  |  | 
|  | for ( K k : map.keySet() ) { | 
|  | newMap.put( k, null ); | 
|  | } | 
|  |  | 
|  | return newMap; | 
|  | } | 
|  |  | 
|  |  | 
|  | public static boolean hasKeys( Map<?, ?> map, String... keys ) { | 
|  | if ( map == null ) { | 
|  | return false; | 
|  | } | 
|  | for ( String key : keys ) { | 
|  | if ( !map.containsKey( key ) ) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  |  | 
|  | public static boolean hasKeys( Map<?, ?> map, Set<String> keys ) { | 
|  | if ( map == null ) { | 
|  | return false; | 
|  | } | 
|  | return map.keySet().containsAll( keys ); | 
|  | } | 
|  | } |