@SuppressWarnings("unchecked")
  protected StackAdvisorRequest prepareStackAdvisorRequest(Request request) {
    try {
      String clusterIdProperty = (String) getRequestProperty(request, CLUSTER_ID_PROPERTY);
      Long clusterId = clusterIdProperty == null ? null : Long.valueOf(clusterIdProperty);

      String serviceName = (String) getRequestProperty(request, SERVICE_NAME_PROPERTY);

      String autoCompleteProperty = (String) getRequestProperty(request, AUTO_COMPLETE_PROPERTY);
      Boolean autoComplete = autoCompleteProperty == null ? false : Boolean.valueOf(autoCompleteProperty);

      String stackName = (String) getRequestProperty(request, STACK_NAME_PROPERTY_ID);
      String stackVersion = (String) getRequestProperty(request, STACK_VERSION_PROPERTY_ID);
      StackAdvisorRequestType requestType = StackAdvisorRequestType
          .fromString((String) getRequestProperty(request, getRequestTypePropertyId()));

      List<String> hosts;
      List<String> services;
      Map<String, Set<String>> hgComponentsMap;
      Map<String, Set<String>> hgHostsMap;
      Map<String, Set<String>> componentHostsMap;
      Map<String, Map<String, Map<String, String>>> configurations;
      Set<RecommendationResponse.ConfigGroup> configGroups;

      // In auto complete case all required fields will be filled will cluster current info
      if (autoComplete) {
        if (clusterId == null || serviceName == null) {
          throw new Exception(
              String.format("Incomplete request, clusterId and/or serviceName are not valid, clusterId=%s, serviceName=%s",
                  clusterId, serviceName));
        }
        Cluster cluster = clusters.getCluster(clusterId);
        List<Host> hostObjects = new ArrayList<>(cluster.getHosts());
        Map<String, Service> serviceObjects = cluster.getServices();

        hosts = hostObjects.stream().map(h -> h.getHostName()).collect(Collectors.toList());
        services = new ArrayList<>(serviceObjects.keySet());
        hgComponentsMap = calculateHostGroupComponentsMap(cluster);
        hgHostsMap = calculateHostGroupHostsMap(cluster);
        componentHostsMap = calculateComponentHostsMap(cluster);
        configurations = calculateConfigurations(cluster, serviceName);

        configGroups = calculateConfigGroups(cluster, request);
      } else {
        /*
       * ClassCastException will occur if hosts or services are empty in the
       * request.
       *
       * @see JsonRequestBodyParser for arrays parsing
       */
        Object hostsObject = getRequestProperty(request, HOST_PROPERTY);
        if (hostsObject instanceof LinkedHashSet) {
          if (((LinkedHashSet)hostsObject).isEmpty()) {
            throw new Exception("Empty host list passed to recommendation service");
          }
        }
        hosts = (List<String>) hostsObject;

        Object servicesObject = getRequestProperty(request, SERVICES_PROPERTY);
        if (servicesObject instanceof LinkedHashSet) {
          if (((LinkedHashSet)servicesObject).isEmpty()) {
            throw new Exception("Empty service list passed to recommendation service");
          }
        }
        services = (List<String>) servicesObject;

        hgComponentsMap = calculateHostGroupComponentsMap(request);
        hgHostsMap = calculateHostGroupHostsMap(request);
        componentHostsMap = calculateComponentHostsMap(hgComponentsMap, hgHostsMap);
        configurations = calculateConfigurations(request);
        configGroups = calculateConfigGroups(request);
      }
      Map<String, String> userContext = readUserContext(request);
      Boolean gplLicenseAccepted = configuration.getGplLicenseAccepted();
      List<ChangedConfigInfo> changedConfigurations =
        requestType == StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES ?
          calculateChangedConfigurations(request) : Collections.emptyList();

      String configsResponseProperty = (String) getRequestProperty(request, CONFIGS_RESPONSE_PROPERTY);
      Boolean configsResponse = configsResponseProperty == null ? false : Boolean.valueOf(configsResponseProperty);

      return StackAdvisorRequestBuilder.
        forStack(stackName, stackVersion).ofType(requestType).forHosts(hosts).
        forServices(services).forHostComponents(hgComponentsMap).
        forHostsGroupBindings(hgHostsMap).
        withComponentHostsMap(componentHostsMap).
        withConfigurations(configurations).
        withConfigGroups(configGroups).
        withChangedConfigurations(changedConfigurations).
        withUserContext(userContext).
        withGPLLicenseAccepted(gplLicenseAccepted).
        withClusterId(clusterId).
        withServiceName(serviceName).
        withConfigsResponse(configsResponse).build();
    } catch (Exception e) {
      LOG.warn("Error occurred during preparation of stack advisor request", e);
      Response response = Response.status(Status.BAD_REQUEST)
          .entity(String.format("Request body is not correct, error: %s", e.getMessage())).build();
      throw new WebApplicationException(response);
    }
  }
Abstract superclass for recommendations and validations.
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java