class AmbariCustomCommandExecutionHelper {

  public void addExecutionCommandsToStage(ActionExecutionContext actionExecutionContext,
      Stage stage, Map<String, String> requestParams, ExecuteCommandJson executeCommandJson)
    throws AmbariException {

    List<RequestResourceFilter> resourceFilters = actionExecutionContext.getResourceFilters();

    for (RequestResourceFilter resourceFilter : resourceFilters) {
      LOG.debug("Received a command execution request, clusterName={}, serviceName={}, request={}",
        actionExecutionContext.getClusterName(), resourceFilter.getServiceName(), actionExecutionContext);

      String actionName = actionExecutionContext.getActionName();
      if (actionName.contains(SERVICE_CHECK_COMMAND_NAME)) {
        findHostAndAddServiceCheckAction(actionExecutionContext, resourceFilter, stage);
      } else if (actionName.equals(DECOMMISSION_COMMAND_NAME)) {
        addDecommissionAction(actionExecutionContext, resourceFilter, stage, executeCommandJson);
      } else if (isValidCustomCommand(actionExecutionContext, resourceFilter)) {

        String commandDetail = getReadableCustomCommandDetail(actionExecutionContext, resourceFilter);
        Map<String, String> extraParams = new HashMap<>();
        String componentName = (null == resourceFilter.getComponentName()) ? null :
            resourceFilter.getComponentName().toLowerCase();

        if (null != componentName && requestParams.containsKey(componentName)) {
          extraParams.put(componentName, requestParams.get(componentName));
        }

        // If command should be retried upon failure then add the option and also the default duration for retry
        if (requestParams.containsKey(KeyNames.COMMAND_RETRY_ENABLED)) {
          extraParams.put(KeyNames.COMMAND_RETRY_ENABLED, requestParams.get(KeyNames.COMMAND_RETRY_ENABLED));
          String commandRetryDuration = ConfigHelper.COMMAND_RETRY_MAX_TIME_IN_SEC_DEFAULT;
          if (requestParams.containsKey(KeyNames.MAX_DURATION_OF_RETRIES)) {
            String commandRetryDurationStr = requestParams.get(KeyNames.MAX_DURATION_OF_RETRIES);
            Integer commandRetryDurationInt = NumberUtils.toInt(commandRetryDurationStr, 0);
            if (commandRetryDurationInt > 0) {
              commandRetryDuration = Integer.toString(commandRetryDurationInt);
            }
          }
          extraParams.put(KeyNames.MAX_DURATION_OF_RETRIES, commandRetryDuration);
        }

        // If command needs to explicitly disable STDOUT/STDERR logging
        if (requestParams.containsKey(KeyNames.LOG_OUTPUT)) {
          extraParams.put(KeyNames.LOG_OUTPUT, requestParams.get(KeyNames.LOG_OUTPUT));
        }

        if(requestParams.containsKey(KeyNames.REFRESH_CONFIG_TAGS_BEFORE_EXECUTION)){
          actionExecutionContext.getParameters().put(KeyNames.REFRESH_CONFIG_TAGS_BEFORE_EXECUTION, requestParams.get(KeyNames.REFRESH_CONFIG_TAGS_BEFORE_EXECUTION));
        }

        RequestOperationLevel operationLevel = actionExecutionContext.getOperationLevel();
        if (operationLevel != null) {
          String clusterName = operationLevel.getClusterName();
          String serviceName = operationLevel.getServiceName();

          if (isTopologyRefreshRequired(actionName, clusterName, serviceName)) {
            extraParams.put(KeyNames.REFRESH_TOPOLOGY, "True");
          }
        }

        addCustomCommandAction(actionExecutionContext, resourceFilter, stage, extraParams, commandDetail, requestParams);
      } else {
        throw new AmbariException("Unsupported action " + actionName);
      }
    }
  }

}