public synchronized List<ManifestServiceInfo> getStackServices(StackInfo stack) {

    if (null != m_manifest) {
      return m_manifest;
    }

    Map<String, Set<String>> manifestVersions = new HashMap<>();

    for (ManifestService manifest : manifestServices) {
      String name = manifest.serviceName;

      if (!manifestVersions.containsKey(name)) {
        manifestVersions.put(manifest.serviceName, new TreeSet<>());
      }

      manifestVersions.get(manifest.serviceName).add(manifest.version);
    }

    m_manifest = new ArrayList<>();

    for (ServiceInfo si : stack.getServices()) {
      Set<String> versions = manifestVersions.containsKey(si.getName()) ?
          manifestVersions.get(si.getName()) : Collections.singleton(
              null == si.getVersion() ? "" : si.getVersion());

      m_manifest.add(new ManifestServiceInfo(si.getName(), si.getDisplayName(),
          si.getComment(), versions));
    }

    return m_manifest;
  }
Gets the list of stack services, applying information from the version
definition. This will include both services which advertise a version and
those which do not.

@param stack
         the stack for which to get the information
@return the list of {@code ManifestServiceInfo} instances for each service
        in the stack
ambari-server/src/main/java/org/apache/ambari/server/state/repository/VersionDefinitionXml.java