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

net.jangaroo.jooc.mvnplugin.util.MergeHelper Maven / Gradle / Ivy

The newest version!
package net.jangaroo.jooc.mvnplugin.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MergeHelper {
  @SafeVarargs
  private static  Map mergeMaps(MergeOptions mergeOptions, Map... maps) {
    Map result = new HashMap<>();

    for (Map map : maps) {
      mergeMapIntoBaseMap(result, map, mergeOptions);
    }

    return result;
  }

  public static  void mergeMapIntoBaseMap(Map baseMap, Map mapToMerge, MergeOptions mergeOptions) {
    for (S key : mapToMerge.keySet()) {
      baseMap.put(key, mergeValues(baseMap.get(key), mapToMerge.get(key), mergeOptions));
    }
  }

  @SafeVarargs
  private static  List mergeLists(MergeOptions mergeOptions, List... lists) {
    List result = new ArrayList<>();

    for (List list : lists) {
      mergeListIntoBaseList(result, list, mergeOptions);
    }

    return result;
  }

  private static  void mergeListIntoBaseList(List baseList, List listToMerge, MergeOptions mergeOptions) {
    for (int i = 0; i < listToMerge.size(); i++) {
      while (i >= baseList.size()) {
        baseList.add(null);
      }
      baseList.set(i, mergeValues(baseList.get(i), listToMerge.get(i), mergeOptions));
    }
  }

  private static  T mergeValues(S value1, T value2, MergeOptions mergeOptions) {
    if (value2 == null) {
      return null;
    }
    if (value2 instanceof Map) {
      if (mergeOptions.mapStrategy == MapStrategy.MERGE && value1 instanceof Map) {
        //noinspection unchecked
        return (T) mergeMaps(mergeOptions, (Map) value1, (Map) value2);
      } else {
        // calling mergeMaps with a single parameter is like a deep copy
        //noinspection unchecked
        return (T) mergeMaps(mergeOptions, (Map) value2);
      }
    } else if (value2 instanceof List) {
      if (!(value1 instanceof List)) {
        // calling mergeLists with a single parameter is like a deep copy
        //noinspection unchecked
        return (T) mergeLists(mergeOptions, (List) value2);
      }
      if (mergeOptions.listStrategy == ListStrategy.MERGE) {
        //noinspection unchecked
        return (T) mergeLists(mergeOptions, (List) value1, (List) value2);
      }
      List list = new ArrayList<>();
      if (mergeOptions.listStrategy == ListStrategy.APPEND) {
        //noinspection unchecked
        list.addAll((List) value1);
      }
      //noinspection unchecked
      list.addAll((List) value2);
      // make sure that a deep copy of every item is provided to avoid modification of inner objects
      //noinspection unchecked
      return (T) mergeLists(mergeOptions, list);
    } else {
      return value2;
    }
  }

  public enum ListStrategy {
    REPLACE,
    MERGE,
    APPEND
  }

  public enum MapStrategy {
    REPLACE,
    MERGE
  }

  public static class MergeOptions {

    public final ListStrategy listStrategy;
    public final MapStrategy mapStrategy;

    public MergeOptions() {
      this.listStrategy = ListStrategy.REPLACE;
      this.mapStrategy = MapStrategy.REPLACE;
    }

    public MergeOptions(ListStrategy listStrategy, MapStrategy mapStrategy) {
      this.listStrategy = listStrategy;
      this.mapStrategy = mapStrategy;
    }
  }
}