public PriorPaymentControlResult executePluginPriorCalls(
      final Account account,
      final UUID paymentMethodId,
      final UUID paymentAttemptId,
      final UUID paymentId,
      final String paymentExternalKey,
      final String paymentTransactionExternalKey,
      final PaymentApiType paymentApiType,
      final TransactionType transactionType,
      final HPPType hppType,
      final BigDecimal amount,
      final Currency currency,
      final boolean isApiPayment,
      final List<String> paymentControlPluginNames,
      final Iterable<PluginProperty> pluginProperties,
      final CallContext callContext)
      throws PaymentControlApiException {
    // Return as soon as the first plugin aborts, or the last result for the last plugin
    PriorPaymentControlResult prevResult =
        new DefaultPriorPaymentControlResult(
            false, amount, currency, paymentMethodId, pluginProperties);

    // Those values are adjusted prior each call with the result of what previous call to plugin
    // returned
    UUID inputPaymentMethodId = paymentMethodId;
    BigDecimal inputAmount = amount;
    Currency inputCurrency = currency;
    Iterable<PluginProperty> inputPluginProperties = pluginProperties;
    PaymentControlContext inputPaymentControlContext =
        new DefaultPaymentControlContext(
            account,
            paymentMethodId,
            paymentAttemptId,
            paymentId,
            paymentExternalKey,
            paymentTransactionExternalKey,
            paymentApiType,
            transactionType,
            hppType,
            amount,
            currency,
            isApiPayment,
            callContext);

    for (final String pluginName : paymentControlPluginNames) {
      final PaymentControlPluginApi plugin =
          paymentControlPluginRegistry.getServiceForName(pluginName);
      if (plugin == null) {
        // First call to plugin, we log warn, if plugin is not registered
        log.warn("Skipping unknown payment control plugin {} when fetching results", pluginName);
        continue;
      }
      log.debug("Calling priorCall of plugin {}", pluginName);
      prevResult = plugin.priorCall(inputPaymentControlContext, inputPluginProperties);
      log.debug("Successful executed priorCall of plugin {}", pluginName);
      if (prevResult.getAdjustedPaymentMethodId() != null) {
        inputPaymentMethodId = prevResult.getAdjustedPaymentMethodId();
      }
      if (prevResult.getAdjustedAmount() != null) {
        inputAmount = prevResult.getAdjustedAmount();
      }
      if (prevResult.getAdjustedCurrency() != null) {
        inputCurrency = prevResult.getAdjustedCurrency();
      }
      if (prevResult.getAdjustedPluginProperties() != null) {
        inputPluginProperties = prevResult.getAdjustedPluginProperties();
      }
      if (prevResult.isAborted()) {
        throw new PaymentControlApiAbortException(pluginName);
      }
      inputPaymentControlContext =
          new DefaultPaymentControlContext(
              account,
              inputPaymentMethodId,
              paymentAttemptId,
              paymentId,
              paymentExternalKey,
              paymentTransactionExternalKey,
              paymentApiType,
              transactionType,
              hppType,
              inputAmount,
              inputCurrency,
              isApiPayment,
              callContext);
    }
    // Rebuild latest result to include inputPluginProperties
    prevResult =
        new DefaultPriorPaymentControlResult(
            prevResult.isAborted(),
            inputPaymentMethodId,
            inputAmount,
            inputCurrency,
            inputPluginProperties);
    return prevResult;
  }