@RequestMapping(value = "/change", method = RequestMethod.POST)
 public String changePassword(
     @Valid final UpdatePwdForm form,
     final BindingResult bindingResult,
     final Model model,
     final RedirectAttributes redirectModel)
     throws CMSItemNotFoundException {
   if (bindingResult.hasErrors()) {
     prepareErrorMessage(model, UPDATE_PWD_CMS_PAGE);
     return ControllerConstants.Views.Pages.Password.PasswordResetChangePage;
   }
   if (!StringUtils.isBlank(form.getToken())) {
     try {
       customerFacade.updatePassword(form.getToken(), form.getPwd());
       GlobalMessages.addFlashMessage(
           redirectModel,
           GlobalMessages.CONF_MESSAGES_HOLDER,
           "account.confirmation.password.updated");
     } catch (final TokenInvalidatedException e) {
       GlobalMessages.addFlashMessage(
           redirectModel, GlobalMessages.ERROR_MESSAGES_HOLDER, "updatePwd.token.invalidated");
     } catch (final RuntimeException e) {
       GlobalMessages.addFlashMessage(
           redirectModel, GlobalMessages.ERROR_MESSAGES_HOLDER, "updatePwd.token.invalid");
     }
   }
   return REDIRECT_LOGIN;
 }
  @Override
  protected String processRegisterUserRequest(
      final String referer,
      final RegisterForm form,
      final BindingResult bindingResult,
      final Model model,
      final HttpServletRequest request,
      final HttpServletResponse response,
      final RedirectAttributes redirectModel)
      throws CMSItemNotFoundException {
    if (bindingResult.hasErrors()) {
      model.addAttribute(form);
      model.addAttribute(new LoginForm());
      model.addAttribute(new GuestForm());
      GlobalMessages.addErrorMessage(model, "form.global.error");
      final Breadcrumb loginBreadcrumbEntry =
          new Breadcrumb(
              "#",
              getMessageSource()
                  .getMessage("header.link.login", null, getI18nService().getCurrentLocale()),
              null);
      model.addAttribute("breadcrumbs", Collections.singletonList(loginBreadcrumbEntry));

      return handleRegistrationError(model);
    }

    final RegisterData data = new RegisterData();
    data.setFirstName(form.getFirstName());
    data.setLastName(form.getLastName());
    data.setLogin(form.getEmail());
    data.setPassword(form.getPwd());
    data.setTitleCode(form.getTitleCode());
    data.setMobileNumber(form.getMobileNumber());
    try {
      getCustomerFacade().register(data);
      getAutoLoginStrategy().login(form.getEmail().toLowerCase(), form.getPwd(), request, response);

      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "registration.confirmation.message.title");
    } catch (final DuplicateUidException e) {
      LOG.warn("registration failed: " + e);
      model.addAttribute(form);
      model.addAttribute(new LoginForm());
      model.addAttribute(new GuestForm());
      GlobalMessages.addErrorMessage(model, "form.global.error");
      bindingResult.rejectValue("email", "registration.error.account.exists.title");

      return handleRegistrationError(model);
    }

    return REDIRECT_PREFIX + getSuccessRedirect(request, response);
  }
  @RequestMapping(
      value = "/cart/update",
      method = RequestMethod.POST,
      produces = "application/json")
  public String updateCartQuantities(
      @RequestParam("storeNamePost") final String storeId,
      @RequestParam("entryNumber") final long entryNumber,
      @RequestParam("hiddenPickupQty") final long quantity,
      final RedirectAttributes redirectModel)
      throws CommerceCartModificationException {
    final CartModificationData cartModificationData =
        cartFacade.updateCartEntry(entryNumber, storeId);

    if (entryNumber == cartModificationData.getEntry().getEntryNumber().intValue()) {
      final CartModificationData cartModification =
          cartFacade.updateCartEntry(entryNumber, quantity);
      if (cartModification.getQuantity() == quantity) {
        // Success
        if (cartModification.getQuantity() == 0) {
          // Success in removing entry
          GlobalMessages.addFlashMessage(
              redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "basket.page.message.remove");
        } else {
          // Success in update quantity
          GlobalMessages.addFlashMessage(
              redirectModel,
              GlobalMessages.CONF_MESSAGES_HOLDER,
              "basket.page.message.update.pickupinstoreitem");
        }
      } else {
        // Less than successful
        GlobalMessages.addFlashMessage(
            redirectModel,
            GlobalMessages.ERROR_MESSAGES_HOLDER,
            "basket.information.quantity.reducedNumberOfItemsAdded."
                + cartModification.getStatusCode());
      }
    } else if (!CommerceCartModificationStatus.SUCCESS.equals(
        cartModificationData.getStatusCode())) {
      // When update pickupInStore happens to be same as existing entry with POS and SKU and that
      // merged POS has lower stock
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.ERROR_MESSAGES_HOLDER,
          "basket.information.quantity.reducedNumberOfItemsAdded."
              + cartModificationData.getStatusCode());
    }

    return REDIRECT_PREFIX + "/cart";
  }
  @RequestMapping(value = "/update-password", method = RequestMethod.POST)
  @RequireHardLogIn
  public String updatePassword(
      final UpdatePasswordForm updatePasswordForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes)
      throws CMSItemNotFoundException {
    getPasswordValidator().validate(updatePasswordForm, bindingResult);
    if (!bindingResult.hasErrors()) {
      if (updatePasswordForm.getNewPassword().equals(updatePasswordForm.getCheckNewPassword())) {
        try {
          customerFacade.changePassword(
              updatePasswordForm.getCurrentPassword(), updatePasswordForm.getNewPassword());
        } catch (final PasswordMismatchException localException) {
          bindingResult.rejectValue(
              "currentPassword",
              "profile.currentPassword.invalid",
              new Object[] {},
              "profile.currentPassword.invalid");
        }
      } else {
        bindingResult.rejectValue(
            "checkNewPassword",
            "validation.checkPwd.equals",
            new Object[] {},
            "validation.checkPwd.equals");
      }
    }

    if (bindingResult.hasErrors()) {
      GlobalMessages.addErrorMessage(model, "form.global.error");
      storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_PASSWORD_CMS_PAGE));
      setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_PASSWORD_CMS_PAGE));

      model.addAttribute(
          "breadcrumbs",
          accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile.updatePasswordForm"));
      return getViewForPage(model);
    } else {
      GlobalMessages.addFlashMessage(
          redirectAttributes,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "text.account.confirmation.password.updated",
          null);
      return REDIRECT_TO_PROFILE_PAGE;
    }
  }
  @RequestMapping(value = "/request/external", method = RequestMethod.POST)
  public String externalPasswordRequest(
      @Valid final ForgottenPwdForm form,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectModel)
      throws CMSItemNotFoundException {
    storeCmsPageInModel(model, getContentPageForLabelOrId(null));
    setUpMetaDataForContentPage(model, getContentPageForLabelOrId(null));
    model.addAttribute(
        WebConstants.BREADCRUMBS_KEY,
        resourceBreadcrumbBuilder.getBreadcrumbs("forgottenPwd.title"));

    if (bindingResult.hasErrors()) {
      return ControllerConstants.Views.Pages.Password.PasswordResetRequest;
    } else {
      try {
        customerFacade.forgottenPassword(form.getEmail());
        GlobalMessages.addFlashMessage(
            redirectModel,
            GlobalMessages.CONF_MESSAGES_HOLDER,
            "account.confirmation.forgotten.password.link.sent");
      } catch (final UnknownIdentifierException unknownIdentifierException) {
        LOG.warn("Email: " + form.getEmail() + " does not exist in the database.");
      }
      return REDIRECT_PWD_REQ_CONF;
    }
  }
  @RequestMapping(method = RequestMethod.GET)
  public String get(
      final Model model, final HttpServletRequest request, final HttpServletResponse response)
      throws CMSItemNotFoundException {
    // Check for CMS Page where label or id is like /page
    final ContentPageModel pageForRequest = getContentPageForRequest(request);
    if (pageForRequest != null) {
      storeCmsPageInModel(model, pageForRequest);
      setUpMetaDataForContentPage(model, pageForRequest);
      model.addAttribute(
          WebConstants.BREADCRUMBS_KEY,
          contentPageBreadcrumbBuilder.getBreadcrumbs(pageForRequest));
      return getViewForPage(pageForRequest);
    }

    // No page found - display the notFound page with error from controller
    storeCmsPageInModel(model, getContentPageForLabelOrId(ERROR_CMS_PAGE));
    setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ERROR_CMS_PAGE));

    model.addAttribute(
        WebConstants.MODEL_KEY_ADDITIONAL_BREADCRUMB,
        resourceBreadcrumbBuilder.getBreadcrumbs("breadcrumb.not.found"));
    GlobalMessages.addErrorMessage(model, "system.error.page.not.found");

    response.setStatus(HttpServletResponse.SC_NOT_FOUND);

    return ControllerConstants.Views.Pages.Error.ErrorNotFoundPage;
  }
 protected String errorUpdatingEmail(final Model model) throws CMSItemNotFoundException {
   GlobalMessages.addErrorMessage(model, "form.global.error");
   storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_EMAIL_CMS_PAGE));
   setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_EMAIL_CMS_PAGE));
   model.addAttribute(
       "breadcrumbs", accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile"));
   return getViewForPage(model);
 }
  @RequestMapping(value = "/update-profile", method = RequestMethod.POST)
  @RequireHardLogIn
  public String updateProfile(
      final UpdateProfileForm updateProfileForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes)
      throws CMSItemNotFoundException {
    getProfileValidator().validate(updateProfileForm, bindingResult);

    String returnAction = ControllerConstants.Views.Pages.Account.AccountProfileEditPage;
    final CustomerData currentCustomerData = customerFacade.getCurrentCustomer();
    final CustomerData customerData = new CustomerData();
    customerData.setTitleCode(updateProfileForm.getTitleCode());
    customerData.setFirstName(updateProfileForm.getFirstName());
    customerData.setLastName(updateProfileForm.getLastName());
    customerData.setUid(currentCustomerData.getUid());
    customerData.setDisplayUid(currentCustomerData.getDisplayUid());

    model.addAttribute("titleData", userFacade.getTitles());

    if (bindingResult.hasErrors()) {
      GlobalMessages.addErrorMessage(model, "form.global.error");
    } else {
      try {
        customerFacade.updateProfile(customerData);
        GlobalMessages.addFlashMessage(
            redirectAttributes,
            GlobalMessages.CONF_MESSAGES_HOLDER,
            "text.account.profile.confirmationUpdated",
            null);
        returnAction = REDIRECT_TO_PROFILE_PAGE;
      } catch (final DuplicateUidException e) {
        bindingResult.rejectValue("email", "registration.error.account.exists.title");
        GlobalMessages.addErrorMessage(model, "form.global.error");
      }
    }

    storeCmsPageInModel(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
    setUpMetaDataForContentPage(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
    model.addAttribute(
        "breadcrumbs", accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile"));
    return returnAction;
  }
  @RequestMapping(value = "/select-suggested-address", method = RequestMethod.POST)
  public String doSelectSuggestedAddress(
      final AddressForm addressForm, final RedirectAttributes redirectModel) {
    final Set<String> resolveCountryRegions =
        org.springframework.util.StringUtils.commaDelimitedListToSet(
            Config.getParameter("resolve.country.regions"));

    final AddressData selectedAddress = new AddressData();
    selectedAddress.setId(addressForm.getAddressId());
    selectedAddress.setTitleCode(addressForm.getTitleCode());
    selectedAddress.setFirstName(addressForm.getFirstName());
    selectedAddress.setLastName(addressForm.getLastName());
    selectedAddress.setLine1(addressForm.getLine1());
    selectedAddress.setLine2(addressForm.getLine2());
    selectedAddress.setTown(addressForm.getTownCity());
    selectedAddress.setPostalCode(addressForm.getPostcode());
    selectedAddress.setBillingAddress(false);
    selectedAddress.setShippingAddress(true);
    selectedAddress.setVisibleInAddressBook(true);

    final CountryData countryData = i18NFacade.getCountryForIsocode(addressForm.getCountryIso());
    selectedAddress.setCountry(countryData);

    if (resolveCountryRegions.contains(countryData.getIsocode())) {
      if (addressForm.getRegionIso() != null && !StringUtils.isEmpty(addressForm.getRegionIso())) {
        final RegionData regionData =
            getI18NFacade().getRegion(addressForm.getCountryIso(), addressForm.getRegionIso());
        selectedAddress.setRegion(regionData);
      }
    }

    if (resolveCountryRegions.contains(countryData.getIsocode())) {
      if (addressForm.getRegionIso() != null && !StringUtils.isEmpty(addressForm.getRegionIso())) {
        final RegionData regionData =
            getI18NFacade().getRegion(addressForm.getCountryIso(), addressForm.getRegionIso());
        selectedAddress.setRegion(regionData);
      }
    }

    if (Boolean.TRUE.equals(addressForm.getEditAddress())) {
      selectedAddress.setDefaultAddress(
          Boolean.TRUE.equals(addressForm.getDefaultAddress())
              || userFacade.getAddressBook().size() <= 1);
      userFacade.editAddress(selectedAddress);
    } else {
      selectedAddress.setDefaultAddress(
          Boolean.TRUE.equals(addressForm.getDefaultAddress()) || userFacade.isAddressBookEmpty());
      userFacade.addAddress(selectedAddress);
    }

    GlobalMessages.addFlashMessage(
        redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "account.confirmation.address.added");

    return REDIRECT_TO_ADDRESS_BOOK_PAGE;
  }
  @RequestMapping(value = "/update-email", method = RequestMethod.POST)
  @RequireHardLogIn
  public String updateEmail(
      final UpdateEmailForm updateEmailForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes,
      final HttpServletRequest request)
      throws CMSItemNotFoundException {
    getEmailValidator().validate(updateEmailForm, bindingResult);

    String returnAction = REDIRECT_TO_PROFILE_PAGE;

    if (!bindingResult.hasErrors()
        && !updateEmailForm.getEmail().equals(updateEmailForm.getChkEmail())) {
      bindingResult.rejectValue(
          "chkEmail",
          "validation.checkEmail.equals",
          new Object[] {},
          "validation.checkEmail.equals");
    }

    if (bindingResult.hasErrors()) {
      returnAction = errorUpdatingEmail(model);
    } else {
      try {
        customerFacade.changeUid(updateEmailForm.getEmail(), updateEmailForm.getPassword());
        GlobalMessages.addFlashMessage(
            redirectAttributes,
            GlobalMessages.CONF_MESSAGES_HOLDER,
            "text.account.profile.confirmationUpdated",
            null);

        // Replace the spring security authentication with the new UID
        final String newUid = customerFacade.getCurrentCustomer().getUid().toLowerCase();
        final Authentication oldAuthentication =
            SecurityContextHolder.getContext().getAuthentication();
        final UsernamePasswordAuthenticationToken newAuthentication =
            new UsernamePasswordAuthenticationToken(
                newUid, null, oldAuthentication.getAuthorities());
        newAuthentication.setDetails(oldAuthentication.getDetails());
        SecurityContextHolder.getContext().setAuthentication(newAuthentication);
      } catch (final DuplicateUidException e) {
        bindingResult.rejectValue("email", "profile.email.unique");
        returnAction = errorUpdatingEmail(model);
      } catch (final PasswordMismatchException passwordMismatchException) {
        bindingResult.rejectValue("password", "profile.currentPassword.invalid");
        returnAction = errorUpdatingEmail(model);
      }
    }

    return returnAction;
  }
 @RequestMapping(value = "/remove-payment-method", method = RequestMethod.POST)
 @RequireHardLogIn
 public String removePaymentMethod(
     final Model model,
     @RequestParam(value = "paymentInfoId") final String paymentMethodId,
     final RedirectAttributes redirectAttributes)
     throws CMSItemNotFoundException {
   userFacade.unlinkCCPaymentInfo(paymentMethodId);
   GlobalMessages.addFlashMessage(
       redirectAttributes,
       GlobalMessages.CONF_MESSAGES_HOLDER,
       "text.account.profile.paymentCart.removed");
   return REDIRECT_TO_PAYMENT_INFO_PAGE;
 }
  @Override
  public ValidationResults validateOnEnter(final RedirectAttributes redirectAttributes) {
    if (!getCheckoutFlowFacade().hasValidCart()) {
      LOG.info("Missing, empty or unsupported cart");
      return ValidationResults.REDIRECT_TO_CART;
    }

    if (getCheckoutFlowFacade().hasNoDeliveryAddress()) {
      GlobalMessages.addFlashMessage(
          redirectAttributes,
          GlobalMessages.INFO_MESSAGES_HOLDER,
          "checkout.multi.deliveryAddress.notprovided");
      return ValidationResults.REDIRECT_TO_DELIVERY_ADDRESS;
    }

    if (getCheckoutFlowFacade().hasNoDeliveryMode()) {
      GlobalMessages.addFlashMessage(
          redirectAttributes,
          GlobalMessages.INFO_MESSAGES_HOLDER,
          "checkout.multi.deliveryMethod.notprovided");
      return ValidationResults.REDIRECT_TO_DELIVERY_METHOD;
    }
    return ValidationResults.SUCCESS;
  }
  @RequestMapping(
      value = "/remove-address/" + ADDRESS_CODE_PATH_VARIABLE_PATTERN,
      method = {RequestMethod.GET, RequestMethod.POST})
  @RequireHardLogIn
  public String removeAddress(
      @PathVariable("addressCode") final String addressCode,
      final RedirectAttributes redirectModel) {
    final AddressData addressData = new AddressData();
    addressData.setId(addressCode);
    userFacade.removeAddress(addressData);

    GlobalMessages.addFlashMessage(
        redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "account.confirmation.address.removed");
    return REDIRECT_TO_ADDRESS_BOOK_PAGE;
  }
  @RequestMapping(
      value = "/cart/update/delivery",
      method = {RequestMethod.GET, RequestMethod.POST})
  public String updateToDelivery(
      @RequestParam("entryNumber") final long entryNumber, final RedirectAttributes redirectModel)
      throws CommerceCartModificationException {
    final CartModificationData cartModificationData = cartFacade.updateCartEntry(entryNumber, null);
    if (CommerceCartModificationStatus.SUCCESS.equals(cartModificationData.getStatusCode())) {
      // Success in update quantity
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "basket.page.message.update.pickupinstoreitem.toship");
    } else {
      // Less than successful
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.ERROR_MESSAGES_HOLDER,
          "basket.information.quantity.reducedNumberOfItemsAdded."
              + cartModificationData.getStatusCode());
    }

    return REDIRECT_PREFIX + "/cart";
  }
  @Override
  public ValidationResults validateOnEnter(final RedirectAttributes redirectAttributes) {

    final ValidationResults result = super.validateOnEnter(redirectAttributes);
    if (ValidationResults.SUCCESS.equals(result)) {
      if (getV2CheckoutFacade().hasNoServiceableMode()) {
        GlobalMessages.addFlashMessage(
            redirectAttributes,
            GlobalMessages.ERROR_MESSAGES_HOLDER,
            "checkout.multi.serviceablemode.notprovided");
        return ValidationResults.REDIRECT_TO_DELIVERY_ADDRESS;
      }
    }

    return result;
  }
 @RequestMapping(
     value = "/set-default-address/" + ADDRESS_CODE_PATH_VARIABLE_PATTERN,
     method = RequestMethod.GET)
 @RequireHardLogIn
 public String setDefaultAddress(
     @PathVariable("addressCode") final String addressCode,
     final RedirectAttributes redirectModel) {
   final AddressData addressData = new AddressData();
   addressData.setDefaultAddress(true);
   addressData.setVisibleInAddressBook(true);
   addressData.setId(addressCode);
   userFacade.setDefaultAddress(addressData);
   GlobalMessages.addFlashMessage(
       redirectModel,
       GlobalMessages.CONF_MESSAGES_HOLDER,
       "account.confirmation.default.address.changed");
   return REDIRECT_TO_ADDRESS_BOOK_PAGE;
 }
 /**
  * Prepares the view to display an error message
  *
  * @throws CMSItemNotFoundException
  */
 protected void prepareErrorMessage(final Model model, final String page)
     throws CMSItemNotFoundException {
   GlobalMessages.addErrorMessage(model, "form.global.error");
   storeCmsPageInModel(model, getContentPageForLabelOrId(page));
   setUpMetaDataForContentPage(model, getContentPageForLabelOrId(page));
 }
  @RequestMapping(
      value = "/edit-address/" + ADDRESS_CODE_PATH_VARIABLE_PATTERN,
      method = RequestMethod.POST)
  @RequireHardLogIn
  public String editAddress(
      final AddressForm addressForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectModel)
      throws CMSItemNotFoundException {
    getAddressValidator().validate(addressForm, bindingResult);
    if (bindingResult.hasErrors()) {
      GlobalMessages.addErrorMessage(model, "form.global.error");
      storeCmsPageInModel(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
      setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
      setUpAddressFormAfterError(addressForm, model);
      return getViewForPage(model);
    }

    model.addAttribute("metaRobots", "noindex,nofollow");

    final AddressData newAddress = new AddressData();
    newAddress.setId(addressForm.getAddressId());
    newAddress.setTitleCode(addressForm.getTitleCode());
    newAddress.setFirstName(addressForm.getFirstName());
    newAddress.setLastName(addressForm.getLastName());
    newAddress.setLine1(addressForm.getLine1());
    newAddress.setLine2(addressForm.getLine2());
    newAddress.setTown(addressForm.getTownCity());
    newAddress.setPostalCode(addressForm.getPostcode());
    newAddress.setBillingAddress(false);
    newAddress.setShippingAddress(true);
    newAddress.setVisibleInAddressBook(true);
    newAddress.setCountry(getI18NFacade().getCountryForIsocode(addressForm.getCountryIso()));

    if (addressForm.getRegionIso() != null && !StringUtils.isEmpty(addressForm.getRegionIso())) {
      newAddress.setRegion(
          getI18NFacade().getRegion(addressForm.getCountryIso(), addressForm.getRegionIso()));
    }

    if (Boolean.TRUE.equals(addressForm.getDefaultAddress())
        || userFacade.getAddressBook().size() <= 1) {
      newAddress.setDefaultAddress(true);
      newAddress.setVisibleInAddressBook(true);
    }

    final AddressVerificationResult<AddressVerificationDecision> verificationResult =
        getAddressVerificationFacade().verifyAddressData(newAddress);
    final boolean addressRequiresReview =
        getAddressVerificationResultHandler()
            .handleResult(
                verificationResult,
                newAddress,
                model,
                redirectModel,
                bindingResult,
                getAddressVerificationFacade().isCustomerAllowedToIgnoreAddressSuggestions(),
                "checkout.multi.address.updated");

    if (addressRequiresReview) {
      model.addAttribute(
          "regions", getI18NFacade().getRegionsForCountryIso(addressForm.getCountryIso()));
      model.addAttribute("country", addressForm.getCountryIso());
      model.addAttribute("edit", Boolean.TRUE);
      storeCmsPageInModel(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
      setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
      return getViewForPage(model);
    }

    userFacade.editAddress(newAddress);

    return REDIRECT_TO_ADDRESS_BOOK_PAGE;
  }
  @RequestMapping(value = "/response", method = RequestMethod.POST)
  @RequireHardLogIn
  public String doHandleSopResponse(
      final HttpServletRequest request,
      @Valid final SopPaymentDetailsForm sopPaymentDetailsForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes)
      throws CMSItemNotFoundException {
    final Map<String, String> resultMap = getRequestParameterMap(request);

    final boolean savePaymentInfo =
        sopPaymentDetailsForm.isSavePaymentInfo()
            || getCheckoutCustomerStrategy().isAnonymousCheckout();
    final PaymentSubscriptionResultData paymentSubscriptionResultData =
        this.getPaymentFacade().completeSopCreateSubscription(resultMap, savePaymentInfo);

    if (paymentSubscriptionResultData.isSuccess()
        && paymentSubscriptionResultData.getStoredCard() != null
        && StringUtils.isNotBlank(
            paymentSubscriptionResultData.getStoredCard().getSubscriptionId())) {
      final CCPaymentInfoData newPaymentSubscription =
          paymentSubscriptionResultData.getStoredCard();

      if (getUserFacade().getCCPaymentInfos(true).size() <= 1) {
        getUserFacade().setDefaultPaymentInfo(newPaymentSubscription);
      }
      getCheckoutFacade().setPaymentDetails(newPaymentSubscription.getId());
    } else if ((paymentSubscriptionResultData.getDecision() != null
            && paymentSubscriptionResultData.getDecision().equalsIgnoreCase("error"))
        || (paymentSubscriptionResultData.getErrors() != null
            && !paymentSubscriptionResultData.getErrors().isEmpty())) {
      // Have SOP errors that we can display

      setupAddPaymentPage(model);

      // Build up the SOP form data and render page containing form
      try {
        setupSilentOrderPostPage(sopPaymentDetailsForm, model);
      } catch (final Exception e) {
        LOG.error("Failed to build beginCreateSubscription request", e);
        GlobalMessages.addErrorMessage(
            model, "checkout.multi.paymentMethod.addPaymentDetails.generalError");
        return enterStep(model, redirectAttributes);
      }

      if (paymentSubscriptionResultData.getErrors() != null
          && !paymentSubscriptionResultData.getErrors().isEmpty()) {
        GlobalMessages.addErrorMessage(model, "checkout.error.paymentethod.formentry.invalid");
        // Add in specific errors for invalid fields
        for (final PaymentErrorField paymentErrorField :
            paymentSubscriptionResultData.getErrors().values()) {
          if (paymentErrorField.isMissing()) {
            bindingResult.rejectValue(
                paymentErrorField.getName(),
                "checkout.error.paymentethod.formentry.sop.missing." + paymentErrorField.getName(),
                "Please enter a value for this field");
          }
          if (paymentErrorField.isInvalid()) {
            bindingResult.rejectValue(
                paymentErrorField.getName(),
                "checkout.error.paymentethod.formentry.sop.invalid." + paymentErrorField.getName(),
                "This value is invalid for this field");
          }
        }
      } else if (paymentSubscriptionResultData.getDecision() != null
          && paymentSubscriptionResultData.getDecision().equalsIgnoreCase("error")) {
        LOG.error(
            "Failed to create subscription. Error occurred while contacting external payment services.");
        GlobalMessages.addErrorMessage(
            model, "checkout.multi.paymentMethod.addPaymentDetails.generalError");
      }

      return ControllerConstants.Views.Pages.MultiStepCheckout.SilentOrderPostPage;
    } else {
      // SOP ERROR!
      LOG.error("Failed to create subscription.  Please check the log files for more information");
      return REDIRECT_URL_ERROR
          + "/?decision="
          + paymentSubscriptionResultData.getDecision()
          + "&reasonCode="
          + paymentSubscriptionResultData.getResultCode();
    }

    return getCheckoutStep().nextStep();
  }