class AlertDefinitionsHolder extends AgentHostDataHolder<AlertDefinitionsAgentUpdateEvent> {

  @Override
  protected AlertDefinitionsAgentUpdateEvent handleUpdate(AlertDefinitionsAgentUpdateEvent current, AlertDefinitionsAgentUpdateEvent update) throws AmbariException {
    Map<Long, AlertCluster> updateClusters = update.getClusters();
    if (updateClusters.isEmpty()) {
      return null;
    }
    AlertDefinitionsAgentUpdateEvent result = null;

    Long hostId = update.getHostId();
    boolean changed = false;
    Map<Long, AlertCluster> existingClusters = current.getClusters();
    Map<Long, AlertCluster> mergedClusters = new HashMap<>();

    switch (update.getEventType()) {
      case UPDATE:
      case DELETE:
        if (!existingClusters.keySet().containsAll(updateClusters.keySet())) {
          LOG.info("Unknown clusters in update, perhaps cluster was removed previously");
        }
        for (Map.Entry<Long, AlertCluster> e : existingClusters.entrySet()) {
          Long clusterId = e.getKey();
          if (!updateClusters.containsKey(clusterId)) {
            mergedClusters.put(clusterId, e.getValue());
          }
        }
        for (Map.Entry<Long, AlertCluster> e : updateClusters.entrySet()) {
          Long clusterId = e.getKey();
          if (existingClusters.containsKey(clusterId)) {
            if (update.getEventType().equals(DELETE) && CollectionUtils.isEmpty(e.getValue().getAlertDefinitions())) {
              changed = true;
            } else {
              AlertCluster mergedCluster = existingClusters.get(e.getKey()).handleUpdate(update.getEventType(), e.getValue());
              if (mergedCluster != null) {
                mergedClusters.put(clusterId, mergedCluster);
                changed = true;
              }
            }
          } else {
            mergedClusters.put(clusterId, e.getValue());
            changed = true;
          }
        }
        LOG.debug("Handled {} of alerts for {} cluster(s) on host with id {}, changed = {}", update.getEventType(), updateClusters.size(), hostId, changed);
        break;
      case CREATE:
        if (!updateClusters.isEmpty()) {
          if (!Sets.intersection(existingClusters.keySet(), updateClusters.keySet()).isEmpty()) {
            throw new AmbariException("Existing clusters in create");
          }
          mergedClusters.putAll(existingClusters);
          mergedClusters.putAll(updateClusters);
          LOG.debug("Handled {} of alerts for {} cluster(s)", update.getEventType(), updateClusters.size());
          changed = true;
        }
        break;
      default:
        LOG.warn("Unhandled event type {}", update.getEventType());
        break;
    }
    if (changed) {
      result = new AlertDefinitionsAgentUpdateEvent(CREATE, mergedClusters, current.getHostName(), hostId);
    }
    return result;
  }

  @Inject public  AlertDefinitionsHolder(AmbariEventPublisher eventPublisher);

}