/** {@inheritDoc} */
  @Override
  public void onApplicationEvent(AgentMappingsUpdateEvent event) {
    Map<Long, AgentCacheEntry> agentCacheMap = nextGenInstrumentationManager.getAgentCacheMap();
    // iterate all caches
    for (AgentCacheEntry agentCacheEntry : agentCacheMap.values()) {
      ConfigurationHolder configurationHolder = agentCacheEntry.getConfigurationHolder();
      Environment cachedEnvironment = configurationHolder.getEnvironment();
      PlatformIdent platformIdent = platformIdentDao.load(agentCacheEntry.getId());
      try {
        // see what 's the new environment for the agent
        Environment environment =
            configurationResolver.getEnvironmentForAgent(
                platformIdent.getDefinedIPs(), platformIdent.getAgentName());

        // fire job only if we have new environment or we were not bounded to any
        // environment
        if ((null == cachedEnvironment)
            || !ObjectUtils.equals(cachedEnvironment.getId(), environment.getId())) {
          EnvironmentMappingUpdateJob mappingUpdateJob = mappingUpdateJobFactory.getObject();
          mappingUpdateJob.setEnvironment(environment);
          mappingUpdateJob.setAgentCacheEntry(agentCacheEntry);

          executor.execute(mappingUpdateJob);
        }
      } catch (BusinessException e) {
        // if we have exception by resolving new environment run job with no new
        // environment
        EnvironmentMappingUpdateJob mappingUpdateJob = mappingUpdateJobFactory.getObject();
        mappingUpdateJob.setAgentCacheEntry(agentCacheEntry);

        executor.execute(mappingUpdateJob);
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  @MethodLog
  public long registerPlatformSensorTypeIdent(long platformId, String fullyQualifiedClassName) {
    PlatformSensorTypeIdent platformSensorTypeIdent;
    List<PlatformSensorTypeIdent> platformSensorTypeIdents =
        platformSensorTypeIdentDao.findByClassNameAndPlatformId(
            fullyQualifiedClassName, platformId);
    if (1 == platformSensorTypeIdents.size()) {
      platformSensorTypeIdent = platformSensorTypeIdents.get(0);
    } else {
      // only if it s not registered we need updating
      PlatformIdent platformIdent = platformIdentDao.load(platformId);
      platformSensorTypeIdent = new PlatformSensorTypeIdent();
      platformSensorTypeIdent.setPlatformIdent(platformIdent);
      platformSensorTypeIdent.setFullyQualifiedClassName(fullyQualifiedClassName);

      Set<SensorTypeIdent> sensorTypeIdents = platformIdent.getSensorTypeIdents();
      sensorTypeIdents.add(platformSensorTypeIdent);

      platformSensorTypeIdentDao.saveOrUpdate(platformSensorTypeIdent);
      platformIdentDao.saveOrUpdate(platformIdent);
    }

    return platformSensorTypeIdent.getId();
  }
  /** {@inheritDoc} */
  @Override
  @MethodLog
  public long registerMethodSensorTypeIdent(
      long platformId, String fullyQualifiedClassName, Map<String, Object> parameters) {
    MethodSensorTypeIdent methodSensorTypeIdent;

    List<MethodSensorTypeIdent> methodSensorTypeIdents =
        methodSensorTypeIdentDao.findByClassNameAndPlatformId(fullyQualifiedClassName, platformId);
    if (1 == methodSensorTypeIdents.size()) {
      methodSensorTypeIdent = methodSensorTypeIdents.get(0);

      // update preferences
      methodSensorTypeIdent.setSettings(parameters);
      methodSensorTypeIdentDao.saveOrUpdate(methodSensorTypeIdent);
    } else {
      // only if the new sensor is registered we need to update the platform ident
      PlatformIdent platformIdent = platformIdentDao.load(platformId);
      methodSensorTypeIdent = new MethodSensorTypeIdent();
      methodSensorTypeIdent.setPlatformIdent(platformIdent);
      methodSensorTypeIdent.setFullyQualifiedClassName(fullyQualifiedClassName);
      methodSensorTypeIdent.setSettings(parameters);

      Set<SensorTypeIdent> sensorTypeIdents = platformIdent.getSensorTypeIdents();
      sensorTypeIdents.add(methodSensorTypeIdent);

      methodSensorTypeIdentDao.saveOrUpdate(methodSensorTypeIdent);
      platformIdentDao.saveOrUpdate(platformIdent);
    }

    return methodSensorTypeIdent.getId();
  }
  /** {@inheritDoc} */
  @Override
  @MethodLog
  public synchronized long registerPlatformIdent(
      List<String> definedIPs, String agentName, String version) throws BusinessException {
    if (log.isInfoEnabled()) {
      log.info("Trying to register Agent '" + agentName + "'");
    }

    // find existing registered
    List<PlatformIdent> platformIdentResults;
    if (ipBasedAgentRegistration) {
      platformIdentResults = platformIdentDao.findByNameAndIps(agentName, definedIPs);
    } else {
      platformIdentResults = platformIdentDao.findByName(agentName);
    }

    PlatformIdent platformIdent = new PlatformIdent();
    platformIdent.setAgentName(agentName);
    if (1 == platformIdentResults.size()) {
      platformIdent = platformIdentResults.get(0);
    } else if (platformIdentResults.size() > 1) {
      // this cannot occur anymore, if it occurs, then there is something totally wrong!
      log.error(
          "More than one platform ident has been retrieved! Please send your Database to the NovaTec inspectIT support!");
      throw new BusinessException(
          "Register the agent with name "
              + agentName
              + " and following network interfaces "
              + definedIPs
              + ".",
          AgentManagementErrorCodeEnum.MORE_THAN_ONE_AGENT_REGISTERED);
    }

    // always update the time stamp and ips, no matter if this is an old or new record.
    platformIdent.setTimeStamp(new Timestamp(GregorianCalendar.getInstance().getTimeInMillis()));
    platformIdent.setDefinedIPs(definedIPs);

    // also always update the version information of the agent
    platformIdent.setVersion(version);

    platformIdentDao.saveOrUpdate(platformIdent);

    agentStatusDataProvider.registerConnected(platformIdent.getId());

    if (log.isInfoEnabled()) {
      log.info(
          "Successfully registered the Agent '"
              + agentName
              + "' with id "
              + platformIdent.getId()
              + ", version "
              + version
              + " and following network interfaces:");
      printOutDefinedIPs(definedIPs);
    }
    return platformIdent.getId();
  }
  /**
   * {@inheritDoc}
   *
   * @throws BusinessException
   */
  @Override
  @MethodLog
  public void unregisterPlatformIdent(List<String> definedIPs, String agentName)
      throws BusinessException {
    log.info("Trying to unregister the Agent with following network interfaces:");
    printOutDefinedIPs(definedIPs);

    List<PlatformIdent> platformIdentResults =
        platformIdentDao.findByNameAndIps(agentName, definedIPs);

    if (1 == platformIdentResults.size()) {
      PlatformIdent platformIdent = platformIdentResults.get(0);
      agentStatusDataProvider.registerDisconnected(platformIdent.getId());
      log.info(
          "The Agent '" + platformIdent.getAgentName() + "' has been successfully unregistered.");
    } else if (platformIdentResults.size() > 1) {
      // this cannot occur anymore, if it occurs, then there is something totally wrong!
      log.error(
          "More than one platform ident has been retrieved! Please send your Database to the NovaTec inspectIT support!");
      throw new BusinessException(
          "Unregister the agent with name "
              + agentName
              + " and following network interfaces "
              + definedIPs
              + ".",
          AgentManagementErrorCodeEnum.MORE_THAN_ONE_AGENT_REGISTERED);
    } else {
      log.warn(
          "No registered agent with given network interfaces exists. Unregistration is aborted.");
      throw new BusinessException(
          "Unregister the agent with name "
              + agentName
              + " and following network interfaces "
              + definedIPs
              + ".",
          AgentManagementErrorCodeEnum.AGENT_DOES_NOT_EXIST);
    }
  }
  /** {@inheritDoc} */
  @Override
  @Transactional
  @MethodLog
  public long registerJmxSensorTypeIdent(long platformId, String fullyQualifiedClassName) {
    JmxSensorTypeIdent jmxSensorTypeIdent = new JmxSensorTypeIdent();
    jmxSensorTypeIdent.setFullyQualifiedClassName(fullyQualifiedClassName);

    List<JmxSensorTypeIdent> jmxSensorTypeIdents =
        jmxSensorTypeIdentDao.findByExample(platformId, jmxSensorTypeIdent);
    if (1 == jmxSensorTypeIdents.size()) {
      jmxSensorTypeIdent = jmxSensorTypeIdents.get(0);
    } else {
      PlatformIdent platformIdent = platformIdentDao.load(platformId);
      jmxSensorTypeIdent.setPlatformIdent(platformIdent);

      Set<SensorTypeIdent> sensorTypeIdents = platformIdent.getSensorTypeIdents();
      sensorTypeIdents.add(jmxSensorTypeIdent);

      jmxSensorTypeIdentDao.saveOrUpdate(jmxSensorTypeIdent);
      platformIdentDao.saveOrUpdate(platformIdent);
    }

    return jmxSensorTypeIdent.getId();
  }