class BlueprintConfigurationProcessor {

  public Set<String> getRequiredHostGroups() {
    Set<String> requiredHostGroups = new HashSet<>();
    Collection<Map<String, Map<String, PropertyUpdater>>> updaters = createCollectionOfUpdaters();

    // Iterate all registered updaters and collect host groups referenced by related properties and
    // extracted by the updaters
    for (Map<String, Map<String, PropertyUpdater>> updaterMap : updaters) {
      for (Map.Entry<String, Map<String, PropertyUpdater>> entry : updaterMap.entrySet()) {
        String type = entry.getKey();
        for (Map.Entry<String, PropertyUpdater> updaterEntry : entry.getValue().entrySet()) {
          String propertyName = updaterEntry.getKey();
          PropertyUpdater updater = updaterEntry.getValue();

          // cluster scoped configuration which also includes all default and BP properties
          Map<String, Map<String, String>> clusterProps = clusterTopology.getConfiguration().getFullProperties();
          Map<String, String> typeMap = clusterProps.get(type);
          if (typeMap != null && typeMap.containsKey(propertyName) && typeMap.get(propertyName) != null) {
            requiredHostGroups.addAll(updater.getRequiredHostGroups(
              propertyName, typeMap.get(propertyName), clusterProps, clusterTopology));
          }

          // host group configs
          for (HostGroupInfo groupInfo : clusterTopology.getHostGroupInfo().values()) {
            Map<String, Map<String, String>> hgConfigProps = groupInfo.getConfiguration().getProperties();
            Map<String, String> hgTypeMap = hgConfigProps.get(type);
            if (hgTypeMap != null && hgTypeMap.containsKey(propertyName)) {
              requiredHostGroups.addAll(updater.getRequiredHostGroups(
                propertyName, hgTypeMap.get(propertyName), hgConfigProps, clusterTopology));
            }
          }
        }
      }
    }

    // Iterate through all user defined properties (blueprint + cluster template only, no stack defaults) that do not
    // have a registered updater. These properties can reference host groups too which should be extracted by the default
    // updater
    Set<Pair<String, String>> propertiesWithUpdaters = getAllPropertiesWithUpdaters(updaters);

    // apply default updater on cluster config
    Map<String, Map<String, String>> userDefinedClusterProperties = clusterTopology.getConfiguration().getFullProperties(1);
    addRequiredHostgroupsByDefaultUpdater(userDefinedClusterProperties, propertiesWithUpdaters, requiredHostGroups);
    // apply default updater on hostgroup configs
    clusterTopology.getHostGroupInfo().values().stream().forEach(
      hostGroup -> {
        Configuration hostGroupConfig = hostGroup.getConfiguration();
        Map<String, Map<String, String>> hostGroupConfigProps = hostGroupConfig.getFullProperties(1);
        addRequiredHostgroupsByDefaultUpdater(hostGroupConfigProps, propertiesWithUpdaters, requiredHostGroups);
      });
    return requiredHostGroups;
  }

  public  BlueprintConfigurationProcessor(ClusterTopology clusterTopology);

}