
// MapUtilsTester.java
// https://www.baeldung.com/apache-commons-map-utils
// Andrew Davison, ad@coe.psu.ac.th, May 2023

/* Illustrates functions from MapUtils:
      * 1D, 2D arrays --> maps
      * verbosePrint
      * default values
      * invertMap
      * fixedSizeMap
      * predicatedMap
      * populateMap
      * lazyMap

   Also see:
      LRUMapTester.java
      OrderedMapTester.java
      ExpiringMapTester
      TransformedMapTester
      SplitMapTester
      PredicateMapTester.java

   Usage:
    > compile MapUtilsTester.java
    > run MapUtilsTester
*/


import java.util.*;

import org.apache.commons.collections4.*;



public class MapUtilsTester
{

  public static void main(String[] args) 
  {
    String[][] colors2D = new String[][] { 
                     { "red", "#FF0000" }, 
                     { "green", "#00FF00" },
                     { "blue", "#0000FF" } };

    String[] colors = { "red", "#FF0000", 
                        "green", "#00FF00", 
                        "blue", "#0000FF" };

    // ---------------------------------

    System.out.println("2D array --> map:");
    Map<String, String> colorMap = 
         MapUtils.putAll(new HashMap<>(), colors2D);
    System.out.println("map: " + colorMap);
    System.out.println("Red value: " + colorMap.get("red"));


    System.out.println("\n1D array --> map:");
    colorMap = MapUtils.putAll(new HashMap<>(), colors);
    System.out.println("map: " + colorMap);
    System.out.println("Red value: " + colorMap.get("red"));

    MapUtils.verbosePrint(System.out, "verbose print", colorMap);

    // ---------------------------------

    System.out.println("\nUse default values:");
    String defaultCol = "COLOR_NOT_FOUND";
    System.out.println("Get black value: " +
                 MapUtils.getString(colorMap, "black", defaultCol));
    System.out.println("Get red value from null map: " +
                  MapUtils.getString(null, "red", defaultCol));

    // ---------------------------------

    Map<String, String> invColorMap = MapUtils.invertMap(colorMap);
    System.out.println("\nInverted map: " + invColorMap);

    // ---------------------------------

    System.out.println("\nCreate a fixed size map:");
    Map<String, String> fixedMap = 
               MapUtils.fixedSizeMap(MapUtils.putAll(
                    new HashMap<>(), colors));
    System.out.println("  " + fixedMap);
    System.out.println("Try to add a value");
    try {  fixedMap.put("orange", "#FFA500");  }
    catch(IllegalArgumentException e)
    {  System.out.println(e);  }

    // ---------------------------------

    System.out.println("\nCreate a map with unique values:");
    Map<String, String> uniqValMap = 
               MapUtils.predicatedMap(colorMap, 
                           null,    // no key predicate
                           PredicateUtils.uniquePredicate());
    System.out.println("  " + uniqValMap);
    System.out.println("Try to add pink-#FF0000");
    try {  uniqValMap.put("pink", "#FF0000");  }
    catch(IllegalArgumentException e)
    {  System.out.println(e);  }

    System.out.println("\nCreate a map with values that must be hexs:");
    uniqValMap =  MapUtils.predicatedMap(colorMap, 
                      null,   // key
                      v -> (v.matches("#[0-9a-fA-F]+") && 
                            v.length() == 7) );    // value

    System.out.println("  " + uniqValMap);
    System.out.println("Try to add pink-#pink");
    try {  uniqValMap.put("pink", "#pink");  }
    catch(IllegalArgumentException e)
    {  System.out.println(e);  }


    // -------------------------------------------

    System.out.println("\nPopulate a map");

    List<String> names = Arrays.asList(
          "Andy", "John", "Jane", "Ben", "Joe", "Peter");

    Map<String, Integer> numsMap = new TreeMap<>();

    MapUtils.populateMap(numsMap, names,
                       s -> s.toLowerCase(),
                       s -> s.length()  // key ==> value
                       );

    System.out.println("  " + numsMap);


    // ---------------------------------

    System.out.println("\nA lazy map (values created on demand):");
    System.out.println(" -- values are string versions of keys:");
    Map<Integer,String> lazyMap = 
                MapUtils.lazyMap(new HashMap<>(),
                            TransformerUtils.stringValueTransformer());
    System.out.println("Lazy map: " + lazyMap);
    System.out.println("Get keys 1, 2, 3:");
    System.out.println(" " + lazyMap.get(1));
    System.out.println(" " + lazyMap.get(2));
    System.out.println(" " + lazyMap.get(3));
    System.out.println("Lazy map: " + lazyMap);


    System.out.println("\nA lazy map -- values are 'v'+key:");
    lazyMap = MapUtils.lazyMap(new HashMap<>(),
                                    k -> "v"+k);   // Transformer
    System.out.println("Lazy map: " + lazyMap);
    System.out.println("Get keys 1, 2, 3:");
    System.out.println(" " + lazyMap.get(1));
    System.out.println(" " + lazyMap.get(2));
    System.out.println(" " + lazyMap.get(3));
    System.out.println("Lazy map: " + lazyMap);
  }  // end of main()

}  // end of MapUtilsTester class
