public void resolveInternal(
      ServiceModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices,
      Map<String, ExtensionModule> extensions, boolean resolveExplicit)
      throws AmbariException {
    if (!serviceInfo.isValid() || !parentModule.isValid()) {
      return;
    }

    LOG.debug("Resolve service");

    // If resolving against parent stack service module (stack inheritance), do not merge if an
    // explicit parent is specified
    if(!StringUtils.isBlank(serviceInfo.getParent()) && !resolveExplicit) {
      return;
    }

    ServiceInfo parent = parentModule.getModuleInfo();

    if (serviceInfo.getComment() == null) {
      serviceInfo.setComment(parent.getComment());
    }
    LOG.info(String.format("Display name service/parent: %s/%s", serviceInfo.getDisplayName(), parent.getDisplayName()));
    if (serviceInfo.getDisplayName() == null) {
      serviceInfo.setDisplayName(parent.getDisplayName());
    }
    if (serviceInfo.getServiceType() == null) {
      serviceInfo.setServiceType(parent.getServiceType());
    }
    if (serviceInfo.getServiceAdvisorType() == null) {
      ServiceInfo.ServiceAdvisorType serviceAdvisorType = parent.getServiceAdvisorType();
      serviceInfo.setServiceAdvisorType(serviceAdvisorType == null ? ServiceInfo.ServiceAdvisorType.PYTHON : serviceAdvisorType);
    }
    if (serviceInfo.getVersion() == null) {
      serviceInfo.setVersion(parent.getVersion());
    }

    if (serviceInfo.getRequiredServices() == null
        || serviceInfo.getRequiredServices().size() == 0) {
      serviceInfo.setRequiredServices(parent.getRequiredServices() != null ?
          parent.getRequiredServices() :
          Collections.emptyList());
    }

    if (serviceInfo.isRestartRequiredAfterChange() == null) {
      serviceInfo.setRestartRequiredAfterChange(parent.isRestartRequiredAfterChange());
    }
    if (serviceInfo.isRestartRequiredAfterRackChange() == null) {
      serviceInfo.setRestartRequiredAfterRackChange(parent.isRestartRequiredAfterRackChange());
    }
    if (serviceInfo.isMonitoringService() == null) {
      serviceInfo.setMonitoringService(parent.isMonitoringService());
    }
    if (serviceInfo.getOsSpecifics().isEmpty() ) {
      serviceInfo.setOsSpecifics(parent.getOsSpecifics());
    }
    if (serviceInfo.getCommandScript() == null) {
      serviceInfo.setCommandScript(parent.getCommandScript());
    }
    if (serviceInfo.getServicePackageFolder() == null) {
      serviceInfo.setServicePackageFolder(parent.getServicePackageFolder());
    }
    if (serviceInfo.getServiceUpgradesFolder() == null) {
      serviceInfo.setServiceUpgradesFolder(parent.getServiceUpgradesFolder());
    }
    if (serviceInfo.getMetricsFile() == null) {
      serviceInfo.setMetricsFile(parent.getMetricsFile());
    }
    if (serviceInfo.getAlertsFile() == null) {
      serviceInfo.setAlertsFile(parent.getAlertsFile());
    }
    if (serviceInfo.getKerberosDescriptorFile() == null) {
      serviceInfo.setKerberosDescriptorFile(parent.getKerberosDescriptorFile());
    }
    if (serviceInfo.getThemesMap().isEmpty()) {
      serviceInfo.setThemesMap(parent.getThemesMap());
    }
    if (serviceInfo.getWidgetsDescriptorFile() == null) {
      serviceInfo.setWidgetsDescriptorFile(parent.getWidgetsDescriptorFile());
    }
    if (serviceInfo.getAdvisorFile() == null) {
      serviceInfo.setAdvisorFile(parent.getAdvisorFile());
    }
    if (serviceInfo.getAdvisorName() == null) {
      serviceInfo.setAdvisorName(parent.getAdvisorName());
    }

    if (serviceInfo.getRoleCommandOrder() == null) {
      serviceInfo.setRoleCommandOrder(parent.getRoleCommandOrder());
    }
    if (serviceInfo.getChecksFolder() == null) {
      serviceInfo.setChecksFolder(parent.getChecksFolder());
    }

    /*
     * Use parent's server actions if the current one does not have any.
     */
    if (serviceInfo.getServerActionsFolder() == null) {
      serviceInfo.setServerActionsFolder(parent.getServerActionsFolder());
    }

    /*
     * If current stack version does not specify the credential store information
     * for the service, then use parent definition.
     */
    if (serviceInfo.getCredentialStoreInfo() == null) {
      serviceInfo.setCredentialStoreInfo(parent.getCredentialStoreInfo());
    }

    /*
     * If current stack version does not specify the single sign-on support details for the service,
     * then use parent definition.
     */
    if (serviceInfo.getSingleSignOnInfo() == null) {
      serviceInfo.setSingleSignOnInfo(parent.getSingleSignOnInfo());
    }

    if (serviceInfo.isSelectionEmpty()) {
      serviceInfo.setSelection(parent.getSelection());
    }

    if (serviceInfo.isMaintainerEmpty()) {
      serviceInfo.setMaintainer(parent.getMaintainer());
    }

    if(null == serviceInfo.getSupportDeleteViaUIField()){
      serviceInfo.setSupportDeleteViaUI(parent.isSupportDeleteViaUI());
    }

    mergeCustomCommands(parent.getCustomCommands(), serviceInfo.getCustomCommands());
    mergeConfigDependencies(parent);
    mergeComponents(parentModule, allStacks, commonServices, extensions);
    mergeConfigurations(parentModule, allStacks, commonServices, extensions);
    mergeThemes(parentModule, allStacks, commonServices, extensions);
    mergeQuickLinksConfigurations(parentModule, allStacks, commonServices, extensions);
    mergeExcludedConfigTypes(parent);

    mergeServiceProperties(parent.getServicePropertyList());
  }
Constructor.

@param stackContext      stack context which provides module access to external functionality
@param serviceInfo       associated service info
@param serviceDirectory  used for all IO interaction with service directory in stack definition
@param isCommonService   flag to mark a service as a common service
ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java