class StackVersionListener {

  @Subscribe
  public void onAmbariEvent(HostComponentVersionAdvertisedEvent event) throws AmbariException {
    LOG.debug("Received event {}", event);

    Cluster cluster = event.getCluster();

    ServiceComponentHost sch = event.getServiceComponentHost();

    String newVersion = event.getVersion();
    if (StringUtils.isEmpty(newVersion)) {
      return;
    }

    // if the cluster is upgrading, there's no need to update the repo version -
    // it better be right
    if (null != event.getRepositoryVersionId() && null == cluster.getUpgradeInProgress()) {
      // !!! make sure the repo_version record actually has the same version.
      // This is NOT true when installing a cluster using a public repo where the
      // exact version is not known in advance.
      RepositoryVersionEntity rve = repositoryVersionDAO.findByPK(event.getRepositoryVersionId());
      if (null != rve) {
        boolean updated = false;
        String currentRepoVersion = rve.getVersion();
        if (!StringUtils.equals(currentRepoVersion, newVersion)) {
          rve.setVersion(newVersion);
          rve.setResolved(true);
          repositoryVersionDAO.merge(rve);
          updated = true;
        } else {
          // the reported versions are the same - we should ensure that the repo
          // is resolved
          if (!rve.isResolved()) {
            rve.setResolved(true);
            repositoryVersionDAO.merge(rve);
            updated = true;
          }
        }
        if (updated) {
          m_hostLevelParamsHolder.get().updateData(m_hostLevelParamsHolder.get().getCurrentData(sch.getHost().getHostId()));
        }
      }
    }

    // Update host component version value if needed
    try {
      // get the component information for the desired stack; if a component
      // moves from UNKNOWN to providing a version, we must do the version
      // advertised check against the target stack
      StackId desiredStackId = sch.getDesiredStackId();

      AmbariMetaInfo ambariMetaInfo = ambariMetaInfoProvider.get();
      ComponentInfo componentInfo = ambariMetaInfo.getComponent(desiredStackId.getStackName(),
          desiredStackId.getStackVersion(), sch.getServiceName(), sch.getServiceComponentName());

      // not advertising a version, do nothing
      if (!componentInfo.isVersionAdvertised()) {
        // that's odd; a version came back - log it and still do nothing
        if (!StringUtils.equalsIgnoreCase(UNKNOWN_VERSION, newVersion)) {
          LOG.warn(
              "ServiceComponent {} doesn't advertise version, however ServiceHostComponent {} on host {} advertised version as {}. Skipping version update",
              sch.getServiceComponentName(), sch.getServiceComponentName(), sch.getHostName(),
              newVersion);
        }
        return;
      }

      ServiceComponent sc = cluster.getService(sch.getServiceName()).getServiceComponent(
          sch.getServiceComponentName());

      // proces the UNKNOWN version
      if (StringUtils.equalsIgnoreCase(UNKNOWN_VERSION, newVersion)) {
        processUnknownDesiredVersion(cluster, sc, sch, newVersion);
        return;
      }

      processComponentAdvertisedVersion(cluster, sc, sch, newVersion);
    } catch (Exception e) {
      LOG.error(
          "Unable to propagate version for ServiceHostComponent on component: {}, host: {}. Error: {}",
          sch.getServiceComponentName(), sch.getHostName(), e.getMessage());
    }
  }

  @Inject public  StackVersionListener(VersionEventPublisher eventPublisher,
                              Provider<AmbariMetaInfo> ambariMetaInfoProvider,
                              Provider<HostLevelParamsHolder> m_hostLevelParamsHolder);

}