@Override
  public void removeServiceMaps(Service service) {
    // 1. remove all maps to the services consumed by service specified
    for (ServiceConsumeMap map : consumeMapDao.findConsumedMapsToRemove(service.getId())) {
      objectProcessManager.scheduleProcessInstance(
          ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, map, null);
    }

    // 2. remove all maps to the services consuming service specified
    for (ServiceConsumeMap map : consumeMapDao.findConsumingMapsToRemove(service.getId())) {
      objectProcessManager.scheduleProcessInstance(
          ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, map, null);
    }
  }
  @Override
  public void addLoadBalancerServiceLink(Service service, LoadBalancerServiceLink serviceLink) {
    if (!service
        .getKind()
        .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.LOADBALANCERSERVICE.name())) {
      return;
    }

    consumeMapDao.createServiceLink(service, serviceLink);
  }
  @Override
  public void removeServiceLink(Service service, ServiceLink serviceLink) {
    ServiceConsumeMap map =
        consumeMapDao.findMapToRemove(service.getId(), serviceLink.getServiceId());

    if (map != null) {
      objectProcessManager.scheduleProcessInstance(
          ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, map, null);
    }
  }
  @Override
  public void cloneConsumingServices(Service fromService, Service toService) {
    List<ServiceLink> linksToCreate = new ArrayList<>();

    for (ServiceConsumeMap map : consumeMapDao.findConsumingServices(fromService.getId())) {
      ServiceLink link;
      List<String> ports =
          DataAccessor.fieldStringList(map, LoadBalancerConstants.FIELD_LB_TARGET_PORTS);
      if (ports == null) {
        link = new ServiceLink(toService.getId(), map.getName());
      } else {
        link = new LoadBalancerServiceLink(toService.getId(), map.getName(), ports);
      }

      link.setConsumingServiceId(map.getServiceId());
      linksToCreate.add(link);
    }

    consumeMapDao.createServiceLinks(linksToCreate);
  }
  private void removeOldServiceMaps(Service service, Map<String, ServiceLink> newServiceLinks) {
    List<? extends ServiceConsumeMap> existingMaps =
        consumeMapDao.findConsumedMapsToRemove(service.getId());
    List<ServiceLink> linksToRemove = new ArrayList<>();

    for (ServiceConsumeMap existingMap : existingMaps) {
      ServiceLink existingLink =
          new ServiceLink(existingMap.getConsumedServiceId(), existingMap.getName());
      if (!newServiceLinks.containsKey(existingLink.getUuid())) {
        linksToRemove.add(existingLink);
      }
    }

    for (ServiceLink linkToRemove : linksToRemove) {
      sdService.removeServiceLink(service, linkToRemove);
    }
  }
  @SuppressWarnings("unchecked")
  protected void populateLoadBalancerServiceLabels(
      Service service, String launchConfigName, Map<String, Object> composeServiceData) {
    if (!service
        .getKind()
        .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.LOADBALANCERSERVICE.name())) {
      return;
    }

    Map<String, String> labels = new HashMap<>();
    if (composeServiceData.get(InstanceConstants.FIELD_LABELS) != null) {
      labels.putAll(
          (HashMap<String, String>) composeServiceData.get(InstanceConstants.FIELD_LABELS));
    }
    // get all consumed services maps
    List<? extends ServiceConsumeMap> consumedServiceMaps =
        consumeMapDao.findConsumedServices(service.getId());
    // for each port, populate the label
    for (ServiceConsumeMap map : consumedServiceMaps) {
      Service consumedService =
          objectManager.loadResource(Service.class, map.getConsumedServiceId());
      List<String> ports =
          DataAccessor.fieldStringList(map, LoadBalancerConstants.FIELD_LB_TARGET_PORTS);
      String consumedServiceName = consumedService.getName();
      if (!service.getEnvironmentId().equals(consumedService.getEnvironmentId())) {
        Environment env =
            objectManager.loadResource(Environment.class, consumedService.getEnvironmentId());
        consumedServiceName = env.getName() + "/" + consumedServiceName;
      }
      String labelName = ServiceDiscoveryConstants.LABEL_LB_TARGET + consumedServiceName;
      StringBuilder bldr = new StringBuilder();
      for (String port : ports) {
        bldr.append(port).append(",");
      }
      if (bldr.length() > 0) {
        labels.put(labelName, bldr.toString().substring(0, bldr.length() - 1));
      }
    }

    if (!labels.isEmpty()) {
      composeServiceData.put(InstanceConstants.FIELD_LABELS, labels);
    }
  }
  private void removeOldServiceMaps(Service service, Map<Long, String> newServiceLinks) {
    List<? extends ServiceConsumeMap> existingMaps =
        consumeMapDao.findConsumedMapsToRemove(service.getId());
    List<ServiceConsumeMap> mapsToRemove = new ArrayList<>();

    for (ServiceConsumeMap existingMap : existingMaps) {
      if (!newServiceLinks.containsKey(existingMap.getConsumedServiceId())) {
        mapsToRemove.add(existingMap);
      } else {
        String newName = newServiceLinks.get(existingMap.getConsumedServiceId());
        String existingName = existingMap.getName();

        if (!StringUtils.equalsIgnoreCase(newName, existingName)) {
          mapsToRemove.add(existingMap);
        }
      }
    }

    for (ServiceConsumeMap mapToRemove : mapsToRemove) {
      objectProcessManager.scheduleProcessInstanceAsync(
          ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, mapToRemove, null);
    }
  }
  private void populateLinksForService(
      Service service,
      Collection<Long> servicesToExportIds,
      Map<String, Object> composeServiceData) {
    List<String> serviceLinksWithNames = new ArrayList<>();
    List<String> externalLinksServices = new ArrayList<>();
    List<? extends ServiceConsumeMap> consumedServiceMaps =
        consumeMapDao.findConsumedServices(service.getId());
    for (ServiceConsumeMap consumedServiceMap : consumedServiceMaps) {
      Service consumedService =
          objectManager.findOne(
              Service.class, SERVICE.ID, consumedServiceMap.getConsumedServiceId());

      String linkName =
          consumedService.getName()
              + ":"
              + (consumedServiceMap.getName() != null
                  ? consumedServiceMap.getName()
                  : consumedService.getName());
      if (servicesToExportIds.contains(consumedServiceMap.getConsumedServiceId())) {
        serviceLinksWithNames.add(linkName);
      } else if (!consumedService.getEnvironmentId().equals(service.getEnvironmentId())) {
        Environment externalEnvironment =
            objectManager.loadResource(Environment.class, consumedService.getEnvironmentId());
        externalLinksServices.add(externalEnvironment.getName() + "/" + linkName);
      }
    }
    if (!serviceLinksWithNames.isEmpty()) {
      composeServiceData.put(
          ServiceDiscoveryConfigItem.LINKS.getDockerName(), serviceLinksWithNames);
    }

    if (!externalLinksServices.isEmpty()) {
      composeServiceData.put(
          ServiceDiscoveryConfigItem.EXTERNALLINKS.getDockerName(), externalLinksServices);
    }
  }
  @Override
  public void addToLoadBalancerService(Service lbSvc, ServiceExposeMap instanceToRegister) {
    if (!lbSvc
        .getKind()
        .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.LOADBALANCERSERVICE.name())) {
      return;
    }

    if (!isActiveService(lbSvc)) {
      return;
    }

    if (!exposeMapDao.isActiveMap(instanceToRegister)) {
      return;
    }

    LoadBalancer lb =
        objectManager.findOne(
            LoadBalancer.class,
            LOAD_BALANCER.SERVICE_ID,
            lbSvc.getId(),
            LOAD_BALANCER.REMOVED,
            null);
    if (lb == null) {
      return;
    }

    ServiceConsumeMap map =
        consumeMapDao.findNonRemovedMap(lbSvc.getId(), instanceToRegister.getServiceId(), null);
    if (map == null) {
      return;
    }

    LoadBalancerTargetInput target =
        new LoadBalancerTargetInput(instanceToRegister, map, jsonMapper);
    lbService.addTargetToLoadBalancer(lb, target);
  }
 private void createNewServiceMaps(Service service, Map<Long, String> newServiceLinks) {
   for (Long consumedServiceId : newServiceLinks.keySet()) {
     String linkName = newServiceLinks.get(consumedServiceId);
     ServiceConsumeMap map =
         consumeMapDao.findNonRemovedMap(service.getId(), consumedServiceId, linkName);
     if (map == null) {
       map =
           objectManager.create(
               ServiceConsumeMap.class,
               SERVICE_CONSUME_MAP.SERVICE_ID,
               service.getId(),
               SERVICE_CONSUME_MAP.CONSUMED_SERVICE_ID,
               consumedServiceId,
               SERVICE_CONSUME_MAP.ACCOUNT_ID,
               service.getAccountId(),
               SERVICE_CONSUME_MAP.NAME,
               linkName);
     }
     if (map.getState().equalsIgnoreCase(CommonStatesConstants.REQUESTED)) {
       objectProcessManager.scheduleProcessInstanceAsync(
           ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_CREATE, map, null);
     }
   }
 }
 @Override
 public void addServiceLink(Service service, ServiceLink serviceLink) {
   consumeMapDao.createServiceLink(service, serviceLink);
 }