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

org.infinispan.commons.util.InfinispanCollections Maven / Gradle / Ivy

There is a newer version: 15.1.0.Dev04
Show newest version
package org.infinispan.commons.util;

import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableMap;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Static helpers for Infinispan-specific collections
 *
 * @author Manik Surtani
 * @since 4.0
 */
public final class InfinispanCollections {

   private InfinispanCollections() {
      // ensuring non-instantiability
   }

   /**
    * A function that converts a type into another one.
    *
    * @param  Input type.
    * @param  Output type.
    */
   public interface Function {

      /**
       * Transforms an instance of the given input into an instace of the
       * type to be returned.
       *
       * @param input Instance of the input type.
       * @return Instance of the output type.
       */
      T transform(E input);
   }

   /**
    * A function that converts an entry into a key/value pair for use in a map.
    * @param  generated key
    * @param  generated value
    * @param  entry input
    */
   public interface MapMakerFunction {
      /**
       * Transforms the given input into a key/value pair for use in a map
       * @param input instance of the input type
       * @return a Map.Entry parameterized with K and V
       */
      Map.Entry transform(E input);
   }

   /**
    * Given a map of well known key/value types, it makes a shallow copy of it
    * while at the same time transforming it's value type to a desired output
    * type. The transformation of the value type is done using a given a
    * function.
    *
    * @param input contains the input key/value pair map
    * @param f function instance to use to transform the value part of the map
    * @param  input map's key type
    * @param  desired output type of the map's value
    * @param  input map's value type
    * @return a shallow copy of the input Map with all its values transformed.
    */
   public static  Map transformMapValue(Map input, Function f) {
      // This screams for a map function! Gimme functional programming pleasee...
      if (input.isEmpty()) return Collections.emptyMap();
      if (input.size() == 1) {
         Map.Entry single = input.entrySet().iterator().next();
         return singletonMap(single.getKey(), f.transform(single.getValue()));
      } else {
         Map copy = new HashMap<>(input.size());
         for (Map.Entry entry : input.entrySet())
            copy.put(entry.getKey(), f.transform(entry.getValue()));
         return unmodifiableMap(copy);
      }
   }

   /**
    * Given a collection, transforms the collection to a map given a {@link MapMakerFunction}
    *
    * @param input contains a collection of type E
    * @param f MapMakerFunction instance to use to transform the collection to a key/value pair
    * @param  output map's key type
    * @param  output type of the map's value
    * @param  input collection's entry type
    * @return a Map with keys and values generated from the input collection
    */
   public static  Map transformCollectionToMap(Collection input, MapMakerFunction f) {
      // This screams for a map function! Gimme functional programming pleasee...
      if (input.isEmpty()) return Collections.emptyMap();
      if (input.size() == 1) {
         E single = input.iterator().next();
         Map.Entry entry = f.transform(single);
         return singletonMap(entry.getKey(), entry.getValue());
      } else {
         Map map = new HashMap<>(input.size());
         for (E e : input) {
            Map.Entry entry = f.transform(e);
            map.put(entry.getKey(), entry.getValue());
         }
         return unmodifiableMap(map);
      }
   }

   /**
    * Returns the elements that are present in s1 but which are not present
    * in s2, without changing the contents of neither s1, nor s2.
    *
    * @param s1 first set
    * @param s2 second set
    * @param  type of objects in Set
    * @return the elements in s1 that are not in s2
    */
   public static  Set difference(Set s1, Set s2) {
      Set copy1 = new HashSet<>(s1);
      copy1.removeAll(new HashSet<>(s2));
      return copy1;
   }

   public static  boolean containsAny(Collection haystack, Collection needles) {
      for (T element : needles) {
         if (haystack.contains(element))
            return true;
      }
      return false;
   }

   public static  void forEach(T[] array, Consumer consumer) {
      final int size = Objects.requireNonNull(array, "Array must be non-null.").length;
      for (int i = 0; i < size; ++i) {
         consumer.accept(array[i]);
      }
   }

   public static void assertNotNullEntries(Map map, String name) {
      Objects.requireNonNull(map, () -> "Map '" + name + "' must be non null.");
      Supplier keySupplier = () -> "Map '" + name + "' contains null key.";
      Supplier valueSupplier = () -> "Map '" + name + "' contains null value.";
      map.forEach((k, v) -> {
         Objects.requireNonNull(k, keySupplier);
         Objects.requireNonNull(v, valueSupplier);
      });
   }

   public static void assertNotNullEntries(Collection collection, String name) {
      Objects.requireNonNull(collection, () -> "Collection '" + name + "' must be non null.");
      Supplier entrySupplier = () -> "Collection '" + name + "' contains null entry.";
      collection.forEach(k -> Objects.requireNonNull(k, entrySupplier));
   }

   public static  Map mergeMaps(Map one, Map second) {
      if (one == null) {
         return second;
      } else if (second == null) {
         return one;
      } else {
         one.putAll(second);
         return one;
      }
   }

   public static  List mergeLists(List one, List second) {
      if (one == null) {
         return second;
      } else if (second == null) {
         return one;
      } else {
         one.addAll(second);
         return one;
      }
   }

   public static Set toObjectSet(Collection collection) {
      //noinspection unchecked
      return collection instanceof Set ?
            (Set) collection :
            new HashSet<>(collection);
   }
}