gt:     protected void validateForm(final ActionContext context) {
context: /*
      This file is part of Cyclos (www.cyclos.org).
      A project of the Social Trade Organisation (www.socialtrade.org).
  
      Cyclos is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
  
      Cyclos is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with Cyclos; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  
   */
  package nl.strohalm.cyclos.controls.payments;
  
  import java.math.BigDecimal;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import javax.servlet.http.HttpServletRequest;
  
  import nl.strohalm.cyclos.annotations.Inject;
  import nl.strohalm.cyclos.controls.ActionContext;
  import nl.strohalm.cyclos.controls.BaseFormAction;
  import nl.strohalm.cyclos.entities.accounts.AccountOwner;
  import nl.strohalm.cyclos.entities.accounts.AccountType;
  import nl.strohalm.cyclos.entities.accounts.transactions.Payment;
  import nl.strohalm.cyclos.entities.accounts.transactions.ScheduledPayment;
  import nl.strohalm.cyclos.entities.accounts.transactions.Transfer;
  import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
  import nl.strohalm.cyclos.entities.customization.fields.CustomField;
  import nl.strohalm.cyclos.entities.customization.fields.CustomFieldPossibleValue;
  import nl.strohalm.cyclos.entities.customization.fields.CustomFieldValue;
  import nl.strohalm.cyclos.entities.customization.fields.PaymentCustomField;
  import nl.strohalm.cyclos.entities.customization.fields.PaymentCustomFieldValue;
  import nl.strohalm.cyclos.entities.exceptions.UnexpectedEntityException;
  import nl.strohalm.cyclos.entities.members.Element;
  import nl.strohalm.cyclos.entities.members.Member;
  import nl.strohalm.cyclos.services.customization.PaymentCustomFieldService;
  import nl.strohalm.cyclos.services.transactions.DoPaymentDTO;
  import nl.strohalm.cyclos.services.transactions.PaymentService;
  import nl.strohalm.cyclos.services.transactions.ScheduledPaymentDTO;
  import nl.strohalm.cyclos.services.transactions.exceptions.AuthorizedPaymentInPastException;
  import nl.strohalm.cyclos.services.transactions.exceptions.CreditsException;
  import nl.strohalm.cyclos.services.transfertypes.TransactionFeePreviewDTO;
  import nl.strohalm.cyclos.services.transfertypes.TransactionFeeService;
  import nl.strohalm.cyclos.services.transfertypes.TransferTypeService;
  import nl.strohalm.cyclos.utils.ActionHelper;
  import nl.strohalm.cyclos.utils.CustomFieldHelper;
  import nl.strohalm.cyclos.utils.CustomFieldHelper.Entry;
  import nl.strohalm.cyclos.utils.RelationshipHelper;
  import nl.strohalm.cyclos.utils.conversion.CoercionHelper;
  import nl.strohalm.cyclos.utils.validation.RequiredError;
  import nl.strohalm.cyclos.utils.validation.ValidationException;
  
  import org.apache.commons.collections.CollectionUtils;
  import org.apache.commons.lang.StringUtils;
  import org.apache.struts.action.ActionForward;
  
  /**
   * Action used to display a message and optionally request the transaction password in order to make a payment
   * @author luis
   */
  public class ConfirmPaymentAction extends BaseFormAction {
  
      private PaymentService            paymentService;
      private TransferTypeService       transferTypeService;
      private TransactionFeeService     transactionFeeService;
      private PaymentCustomFieldService paymentCustomFieldService;
  
      private CustomFieldHelper         customFieldHelper;
  
      @Inject
      public void setCustomFieldHelper(final CustomFieldHelper customFieldHelper) {
          this.customFieldHelper = customFieldHelper;
      }
  
      @Inject
      public void setPaymentCustomFieldService(final PaymentCustomFieldService paymentCustomFieldService) {
          this.paymentCustomFieldService = paymentCustomFieldService;
      }
  
      @Inject
      public void setPaymentService(final PaymentService paymentService) {
          this.paymentService = paymentService;
      }
  
      @Inject
      public void setTransactionFeeService(final TransactionFeeService transactionFeeService) {
          this.transactionFeeService = transactionFeeService;
      }
  
      @Inject
      public void setTransferTypeService(final TransferTypeService transferTypeService) {
          this.transferTypeService = transferTypeService;
      }
  
      @Override
      protected ActionForward handleSubmit(final ActionContext context) throws Exception {
          final ConfirmPaymentForm form = context.getForm();
          final DoPaymentDTO paymentDTO = validatePayment(context);
          // Validate the transaction password if needed
          if (shouldValidateTransactionPassword(context, paymentDTO)) {
              context.checkTransactionPassword(form.getTransactionPassword());
          }
          // Perform the actual payment
          Payment payment;
          try {
              payment = paymentService.doPayment(paymentDTO);
              context.getSession().removeAttribute("payment");
          } catch (final CreditsException e) {
              return context.sendError(actionHelper.resolveErrorKey(e), actionHelper.resolveParameters(e));
          } catch (final UnexpectedEntityException e) {
              return context.sendError("payment.error.invalidTransferType");
          } catch (final AuthorizedPaymentInPastException e) {
              return context.sendError("payment.error.authorizedInPast");
          }
          // Redirect to the next action
          final Map<String, Object> params = new HashMap<String, Object>();
          ActionForward forward;
          if (payment instanceof Transfer) {
              params.put("transferId", payment.getId());
              forward = context.getSuccessForward();
          } else if (payment instanceof ScheduledPayment) {
              params.put("paymentId", payment.getId());
              forward = context.findForward("scheduledPayment");
          } else {
              throw new IllegalStateException("Unknown payment type: " + payment);
          }
          params.put("selectMember", form.getSelectMember());
          params.put("from", form.getFrom());
          return ActionHelper.redirectWithParams(context.getRequest(), forward, params);
      }
  
      @Override
      protected void prepareForm(final ActionContext context) throws Exception {
          final DoPaymentDTO payment = validatePayment(context);
  
          // Clear the from when the same as logged owner
          if (payment.getFrom() != null && context.getAccountOwner().equals(payment.getFrom())) {
              payment.setFrom(null);
          }
  
          // Check for transaction password
          final HttpServletRequest request = context.getRequest();
          final boolean requestTransactionPassword = shouldValidateTransactionPassword(context, payment);
          if (requestTransactionPassword) {
              context.validateTransactionPassword();
          }
  
          final boolean wouldRequireAuthorization = paymentService.wouldRequireAuthorization(payment);
          request.setAttribute("requestTransactionPassword", requestTransactionPassword);
          request.setAttribute("wouldRequireAuthorization", wouldRequireAuthorization);
  
          if (wouldRequireAuthorization && payment.getDate() != null) {
              throw new ValidationException("payment.error.authorizedInPast");
          }
  
          // Fetch related data
          AccountOwner from = payment.getFrom();
          AccountOwner to = payment.getTo();
          final TransferType transferType = transferTypeService.load(payment.getTransferType().getId(), RelationshipHelper.nested(TransferType.Relationships.FROM, AccountType.Relationships.CURRENCY), TransferType.Relationships.TO);
          final BigDecimal amount = payment.getAmount();
          if (from instanceof Member) {
              from = (Member) elementService.load(((Member) from).getId());
              request.setAttribute("fromMember", from);
              payment.setFrom(from);
          }
          if (to instanceof Member) {
              to = (Member) elementService.load(((Member) to).getId());
              request.setAttribute("toMember", to);
              payment.setTo(to);
          }
          // request.setAttribute("relatedMember", from != null ? from.g : to);
          payment.setTransferType(transferType);
          request.setAttribute("unitsPattern", transferType.getFrom().getCurrency().getPattern());
  
          // Store the transaction fees
          final TransactionFeePreviewDTO preview = transactionFeeService.preview(from, to, transferType, amount);
          request.setAttribute("finalAmount", preview.getFinalAmount());
          request.setAttribute("fees", preview.getFees());
  
          // Show the total amount when the original amount has changed (there where fees which deducted from it)
          if (!preview.getAmount().equals(preview.getFinalAmount())) {
              request.setAttribute("totalAmount", preview.getAmount());
          }
  
          // Calculate the transaction fees for every scheduled payment
          final List<ScheduledPaymentDTO> payments = payment.getPayments();
          final boolean isScheduled = CollectionUtils.isNotEmpty(payments);
          if (isScheduled) {
              for (final ScheduledPaymentDTO current : payments) {
                  final TransactionFeePreviewDTO currentPreview = transactionFeeService.preview(from, to, transferType, current.getAmount());
                  current.setFinalAmount(currentPreview.getFinalAmount());
              }
          }
          request.setAttribute("isScheduled", isScheduled);
  
          // Return the custom field values
          final Collection<PaymentCustomFieldValue> customValues = payment.getCustomValues();
          if (customValues != null) {
              final List<PaymentCustomField> customFields = paymentCustomFieldService.list(transferType, false);
              final Collection<Entry> entries = customFieldHelper.buildEntries(customFields, customValues);
              // Load the value for enumerated values, since this collection was built from direct databinding with ids only
              for (final Entry entry : entries) {
                  final CustomField field = entry.getField();
                  final CustomFieldValue fieldValue = entry.getValue();
                  if (field.getType() == CustomField.Type.ENUMERATED) {
                      Long possibleValueId;
                      final CustomFieldPossibleValue possibleValue = fieldValue.getPossibleValue();
                      if (possibleValue != null) {
                          possibleValueId = possibleValue.getId();
                      } else {
                          possibleValueId = CoercionHelper.coerce(Long.class, fieldValue.getValue());
                      }
                      if (possibleValueId != null) {
                          fieldValue.setPossibleValue(paymentCustomFieldService.loadPossibleValue(possibleValueId));
                      }
                  } else if (field.getType() == CustomField.Type.MEMBER) {
                      final Long memberId = CoercionHelper.coerce(Long.class, fieldValue.getValue());
                      if (memberId != null) {
                          final Element element = elementService.load(memberId);
                          if (element instanceof Member) {
                              fieldValue.setMemberValue((Member) element);
                          }
                      }
                  }
              }
              request.setAttribute("customFields", entries);
          }
      }
  
      @Override
  