class ConfigUpgradePack {

  public static ConfigUpgradePack merge(ArrayList<ConfigUpgradePack> cups) {
    // Map <service_name, <component_name, component_changes>>
    Map<String, Map<String, AffectedComponent>> mergedServiceMap = new HashMap<>();

    for (ConfigUpgradePack configUpgradePack : cups) {
      for (AffectedService service : configUpgradePack.services) {
        if (! mergedServiceMap.containsKey(service.name)) {
          mergedServiceMap.put(service.name, new HashMap<>());
        }
        Map<String, AffectedComponent> mergedComponentMap = mergedServiceMap.get(service.name);

        for (AffectedComponent component : service.components) {
          if (! mergedComponentMap.containsKey(component.name)) {
            AffectedComponent mergedComponent = new AffectedComponent();
            mergedComponent.name = component.name;
            mergedComponent.changes = new ArrayList<>();
            mergedComponentMap.put(component.name, mergedComponent);
          }
          AffectedComponent mergedComponent = mergedComponentMap.get(component.name);
          mergedComponent.changes.addAll(component.changes);
        }

      }
    }
    // Convert merged maps into new ConfigUpgradePack
    ArrayList<AffectedService> mergedServices = new ArrayList<>();
    for (String serviceName : mergedServiceMap.keySet()) {
      AffectedService mergedService = new AffectedService();
      Map<String, AffectedComponent> mergedComponentMap = mergedServiceMap.get(serviceName);
      mergedService.name = serviceName;
      mergedService.components = new ArrayList<>(mergedComponentMap.values());
      mergedServices.add(mergedService);
    }

    return new ConfigUpgradePack(mergedServices);
  }

  public  ConfigUpgradePack();
  public  ConfigUpgradePack(List<AffectedService> services);

}