All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.karaf.features.internal.util.MapUtils Maven / Gradle / Ivy

There is a newer version: 4.4.6
Show newest version
/*
 * 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.karaf.features.internal.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;

import static java.util.stream.Collectors.toSet;

public final class MapUtils {

    private MapUtils() {
    }

    public static  Map> invert(Map map) {
        Map> inverted = new HashMap<>(map.size());
        for (Map.Entry entry : map.entrySet()) {
            addToMapSet(inverted, entry.getValue(), entry.getKey());
        }
        return inverted;
    }

    /**
     * Changes mapping from S -> Set<T> to mapping
     * S -> Set<U> using {@link Function} that can change T to
     * U.
     *
     * @param mapset
     * @param function
     * @param  A key that maps to set of values in input and result map
     * @param  A type of input set of values
     * @param  A type of result set of values
     * @return
     */
    public static  Map> apply(Map> mapset, Function function) {
        Map> result = new HashMap<>(mapset.size());
        for (Map.Entry> entry : mapset.entrySet()) {
            result.put(entry.getKey(), apply(entry.getValue(), function));
        }
        return result;
    }

    public static  Set apply(Set set, Function function) {
        Set result = new HashSet<>(set.size());
        for (T t : set) {
            U u = function.apply(t);
            if (u != null) {
                result.add(u);
            }
        }
        return result;
    }

    public static  Map build(Collection col, Function key, Function value) {
        Map result = new HashMap<>(col.size());
        for (S s : col) {
            T t = key.apply(s);
            U u = value.apply(s);
            if (t != null && u != null) {
                result.put(t, u);
            }
        }
        return result;
    }

    public static  Function compose(final Function f1, final Function f2) {
        return s -> f2.apply(f1.apply(s));
    }

    public static  Function map(final Map map) {
        return map::get;
    }

    public static  boolean contains(Map> mapset, S key, T val) {
        Set set = mapset.get(key);
        return set != null && set.contains(val);
    }

    public static  Set flatten(Map> mapset) {
        Set set = new HashSet<>();
        for (Set s : mapset.values()) {
            set.addAll(s);
        }
        return set;
    }

    /**
     * Produces a map where each set value in from map has every element that's in to
     * map's set value removed. If from map is left with empty set value, entire set is removed.
     * @param from
     * @param to
     * @param 
     * @param 
     * @return
     */
    public static  Map> diff(Map> from, Map> to) {
        Map> diff = copyMapSet(from);
        remove(diff, to);
        return diff;
    }

    public static  void add(Map> from, Map> toAdd) {
        for (Map.Entry> entry : toAdd.entrySet()) {
            from.computeIfAbsent(entry.getKey(), k -> new HashSet<>()).addAll(entry.getValue());
        }
    }

    public static  void retain(Map> from, Map> toRetain) {
        for (Iterator>> iterator = from.entrySet().iterator(); iterator.hasNext();) {
            Map.Entry> entry = iterator.next();
            Set s = toRetain.get(entry.getKey());
            if (s != null) {
                entry.getValue().retainAll(s);
            } else {
                iterator.remove();
            }
        }
    }

    /**
     * Removes all values from toRemove map from from map. After removal, set values
     * in from map may be smaller or removed entirely (if there are no more values in given set).
     * @param from
     * @param toRemove
     * @param 
     * @param 
     */
    public static  void remove(Map> from, Map> toRemove) {
        for (Map.Entry> entry : toRemove.entrySet()) {
            Set s = from.get(entry.getKey());
            if (s != null) {
                s.removeAll(entry.getValue());
                if (s.isEmpty()) {
                    from.remove(entry.getKey());
                }
            }
        }
    }

    @SuppressWarnings({
     "unchecked", "rawtypes"
    })
    public static  S copy(S obj) {
        if (obj instanceof List) {
            List r = new ArrayList();
            for (Object o : (List) obj) {
                r.add(copy(o));
            }
            return (S) r;
        } else if (obj instanceof Set) {
            Set r = new HashSet();
            for (Object o : (Set) obj) {
                r.add(copy(o));
            }
            return (S) r;
        } else if (obj instanceof Map) {
            Map r = new HashMap();
            for (Map.Entry e : ((Map) obj).entrySet()) {
                r.put(copy(e.getKey()), copy(e.getValue()));
            }
            return (S) r;
        }
        return obj;
    }

    @SuppressWarnings({
     "rawtypes", "unchecked"
    })
    public static  void copy(S s1, S s2) {
        if (s1 instanceof Collection) {
            for (Object o : (Collection) s1) {
                ((Collection) s2).add(copy(o));
            }
        } else if (s1 instanceof Map) {
            for (Map.Entry e : ((Map) s1).entrySet()) {
                ((Map) s2).put(copy(e.getKey()), copy(e.getValue()));
            }
        } else {
            throw new IllegalArgumentException("Source is not a Collection or a Map");
        }
    }

    public static  Map> copyMapSet(Map> from) {
        Map> to = new HashMap<>();
        copyMapSet(from, to);
        return to;
    }

    public static  void copyMapSet(Map> from, Map> to) {
        for (Map.Entry> entry : from.entrySet()) {
            to.put(entry.getKey(), new HashSet<>(entry.getValue()));
        }
    }

    public static  void addToMapSet(Map> map, S key, T value) {
        map.computeIfAbsent(key, k -> new HashSet<>()).add(value);
    }

    public static  void removeFromMapSet(Map> map, S key, T value) {
        Set values = map.get(key);
        if (values != null) {
            values.remove(value);
            if (values.isEmpty()) {
                map.remove(key);
            }
        }
    }

    public static  Set diff(Set s1, Set s2) {
        Set s = new HashSet<>(s1);
        s.removeAll(s2);
        return s;
    }

    public static  Set map(Set s, Function mapper) {
        return s.stream().map(mapper).collect(toSet());
    }

    public static  Set filter(Set s, Predicate predicate) {
        return s.stream().filter(predicate).collect(toSet());
    }

}