org.training.storefront.controllers.pages.AccountPageController.java Source code

Java tutorial

Introduction

Here is the source code for org.training.storefront.controllers.pages.AccountPageController.java

Source

/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2016 hybris AG
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of hybris
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the
 * license agreement you entered into with hybris.
 *
 *
 */
package org.training.storefront.controllers.pages;

import de.hybris.platform.acceleratorfacades.ordergridform.OrderGridFormFacade;
import de.hybris.platform.acceleratorfacades.product.data.ReadOnlyOrderGridData;
import de.hybris.platform.acceleratorstorefrontcommons.annotations.RequireHardLogIn;
import de.hybris.platform.acceleratorstorefrontcommons.breadcrumb.Breadcrumb;
import de.hybris.platform.acceleratorstorefrontcommons.breadcrumb.ResourceBreadcrumbBuilder;
import de.hybris.platform.acceleratorstorefrontcommons.controllers.ThirdPartyConstants;
import de.hybris.platform.acceleratorstorefrontcommons.controllers.pages.AbstractSearchPageController;
import de.hybris.platform.acceleratorstorefrontcommons.controllers.util.GlobalMessages;
import de.hybris.platform.acceleratorstorefrontcommons.forms.AddressForm;
import de.hybris.platform.acceleratorstorefrontcommons.forms.UpdateEmailForm;
import de.hybris.platform.acceleratorstorefrontcommons.forms.UpdatePasswordForm;
import de.hybris.platform.acceleratorstorefrontcommons.forms.validation.AddressValidator;
import de.hybris.platform.acceleratorstorefrontcommons.forms.validation.EmailValidator;
import de.hybris.platform.acceleratorstorefrontcommons.forms.validation.PasswordValidator;
import de.hybris.platform.acceleratorstorefrontcommons.forms.validation.ProfileValidator;
import de.hybris.platform.acceleratorstorefrontcommons.forms.verification.AddressVerificationResultHandler;
import de.hybris.platform.cms2.exceptions.CMSItemNotFoundException;
import de.hybris.platform.commercefacades.address.AddressVerificationFacade;
import de.hybris.platform.commercefacades.address.data.AddressVerificationResult;
import de.hybris.platform.commercefacades.i18n.I18NFacade;
import de.hybris.platform.commercefacades.order.CheckoutFacade;
import de.hybris.platform.commercefacades.order.OrderFacade;
import de.hybris.platform.commercefacades.order.data.CCPaymentInfoData;
import de.hybris.platform.commercefacades.order.data.OrderData;
import de.hybris.platform.commercefacades.order.data.OrderEntryData;
import de.hybris.platform.commercefacades.order.data.OrderHistoryData;
import de.hybris.platform.commercefacades.product.ProductFacade;
import de.hybris.platform.commercefacades.product.ProductOption;
import de.hybris.platform.commercefacades.product.data.ProductData;
import de.hybris.platform.commercefacades.user.UserFacade;
import de.hybris.platform.commercefacades.user.data.AddressData;
import de.hybris.platform.commercefacades.user.data.CountryData;
import de.hybris.platform.commercefacades.user.data.CustomerData;
import de.hybris.platform.commercefacades.user.data.RegionData;
import de.hybris.platform.commercefacades.user.data.TitleData;
import de.hybris.platform.commercefacades.user.exceptions.PasswordMismatchException;
import de.hybris.platform.commerceservices.address.AddressVerificationDecision;
import de.hybris.platform.commerceservices.customer.DuplicateUidException;
import de.hybris.platform.commerceservices.search.pagedata.PageableData;
import de.hybris.platform.commerceservices.search.pagedata.SearchPageData;
import de.hybris.platform.commerceservices.util.ResponsiveUtils;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.servicelayer.exceptions.UnknownIdentifierException;
import de.hybris.platform.util.Config;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.training.facades.customer.impl.CustomCustomerFacade;
import org.training.facades.product.ProductWishlistConvertFacade;
import org.training.facades.wishlist.impl.WishlistFacade;
import org.training.storefront.controllers.ControllerConstants;
import org.training.storefront.forms.CustomUpdateProfileForm;

/**
 * Controller for home page
 */
@Controller
@Scope("tenant")
@RequestMapping("/my-account")
public class AccountPageController extends AbstractSearchPageController {
    private static final String TEXT_ACCOUNT_ADDRESS_BOOK = "text.account.addressBook";
    private static final String TEXT_ACCOUNT_WISHLIST = "text.account.wishlist";
    private static final String BREADCRUMBS_ATTR = "breadcrumbs";
    private static final String IS_DEFAULT_ADDRESS_ATTR = "isDefaultAddress";
    private static final String COUNTRY_DATA_ATTR = "countryData";
    private static final String ADDRESS_BOOK_EMPTY_ATTR = "addressBookEmpty";
    private static final String TITLE_DATA_ATTR = "titleData";
    private static final String FORM_GLOBAL_ERROR = "form.global.error";
    private static final String PROFILE_CURRENT_PASSWORD_INVALID = "profile.currentPassword.invalid";
    private static final String TEXT_ACCOUNT_PROFILE = "text.account.profile";
    private static final String ADDRESS_DATA_ATTR = "addressData";
    private static final String ADDRESS_FORM_ATTR = "addressForm";

    private static final String WISHLIST_DATA_ATTR = "wishlistData";
    private static final String COUNTRY_ATTR = "country";
    private static final String REGIONS_ATTR = "regions";
    private static final String MY_ACCOUNT_ADDRESS_BOOK_URL = "/my-account/address-book";
    private static final String MY_ACCOUNT_WISHLIST_URL = "/my-account/wishlist";
    // Internal Redirects
    private static final String REDIRECT_TO_ADDRESS_BOOK_PAGE = REDIRECT_PREFIX + MY_ACCOUNT_ADDRESS_BOOK_URL;
    private static final String REDIRECT_TO_PAYMENT_INFO_PAGE = REDIRECT_PREFIX + "/my-account/payment-details";
    private static final String REDIRECT_TO_EDIT_ADDRESS_PAGE = REDIRECT_PREFIX + "/my-account/edit-address/";
    private static final String REDIRECT_TO_UPDATE_EMAIL_PAGE = REDIRECT_PREFIX + "/my-account/update-email";
    private static final String REDIRECT_TO_UPDATE_PROFILE = REDIRECT_PREFIX + "/my-account/update-profile";
    private static final String REDIRECT_TO_PASSWORD_UPDATE_PAGE = REDIRECT_PREFIX + "/my-account/update-password";
    private static final String REDIRECT_TO_ORDER_HISTORY_PAGE = REDIRECT_PREFIX + "/my-account/orders";
    private static final String REDIRECT_TO_WISHLIST_PAGE = REDIRECT_PREFIX + "/my-account/wishlist";
    /**
     * We use this suffix pattern because of an issue with Spring 3.1 where a Uri value is incorrectly extracted if it
     * contains on or more '.' characters. Please see https://jira.springsource.org/browse/SPR-6164 for a discussion on
     * the issue and future resolution.
     */
    private static final String ORDER_CODE_PATH_VARIABLE_PATTERN = "{orderCode:.*}";
    private static final String ADDRESS_CODE_PATH_VARIABLE_PATTERN = "{addressCode:.*}";

    // CMS Pages
    private static final String ACCOUNT_CMS_PAGE = "account";
    private static final String PROFILE_CMS_PAGE = "profile";
    private static final String UPDATE_PASSWORD_CMS_PAGE = "updatePassword";
    private static final String UPDATE_PROFILE_CMS_PAGE = "update-profile";
    private static final String UPDATE_EMAIL_CMS_PAGE = "update-email";
    private static final String ADDRESS_BOOK_CMS_PAGE = "address-book";
    private static final String ADD_EDIT_ADDRESS_CMS_PAGE = "add-edit-address";
    private static final String PAYMENT_DETAILS_CMS_PAGE = "payment-details";
    private static final String ORDER_HISTORY_CMS_PAGE = "orders";
    private static final String ORDER_DETAIL_CMS_PAGE = "order";
    private static final String WISHLIST_CMS_PAGE = "wishlist";

    private static final Logger LOG = Logger.getLogger(AccountPageController.class);

    @Resource(name = "productWishlistConvertFacade")
    private ProductWishlistConvertFacade productWishlistFacade;

    @Resource(name = "orderFacade")
    private OrderFacade orderFacade;

    @Resource(name = "acceleratorCheckoutFacade")
    private CheckoutFacade checkoutFacade;

    @Resource(name = "userFacade")
    private UserFacade userFacade;

    @Resource(name = "customCustomerFacade")
    private CustomCustomerFacade customCustomerFacade;

    @Resource(name = "accountBreadcrumbBuilder")
    private ResourceBreadcrumbBuilder accountBreadcrumbBuilder;

    @Resource(name = "passwordValidator")
    private PasswordValidator passwordValidator;

    @Resource(name = "addressValidator")
    private AddressValidator addressValidator;

    @Resource(name = "profileValidator")
    private ProfileValidator profileValidator;

    @Resource(name = "emailValidator")
    private EmailValidator emailValidator;

    @Resource(name = "i18NFacade")
    private I18NFacade i18NFacade;

    @Resource(name = "addressVerificationFacade")
    private AddressVerificationFacade addressVerificationFacade;

    @Resource(name = "addressVerificationResultHandler")
    private AddressVerificationResultHandler addressVerificationResultHandler;

    @Resource(name = "productVariantFacade")
    private ProductFacade productFacade;

    @Resource(name = "orderGridFormFacade")
    private OrderGridFormFacade orderGridFormFacade;

    @Resource(name = "wishlistFacade")
    private WishlistFacade wishlistFacade;

    PasswordValidator getPasswordValidator() {
        return passwordValidator;
    }

    protected AddressValidator getAddressValidator() {
        return addressValidator;
    }

    protected ProfileValidator getProfileValidator() {
        return profileValidator;
    }

    protected EmailValidator getEmailValidator() {
        return emailValidator;
    }

    protected I18NFacade getI18NFacade() {
        return i18NFacade;
    }

    protected AddressVerificationFacade getAddressVerificationFacade() {
        return addressVerificationFacade;
    }

    protected AddressVerificationResultHandler getAddressVerificationResultHandler() {
        return addressVerificationResultHandler;
    }

    @ModelAttribute("countries")
    public Collection<CountryData> getCountries() {
        return checkoutFacade.getDeliveryCountries();
    }

    @ModelAttribute("titles")
    public Collection<TitleData> getTitles() {
        return userFacade.getTitles();
    }

    @ModelAttribute("countryDataMap")
    public Map<String, CountryData> getCountryDataMap() {
        final Map<String, CountryData> countryDataMap = new HashMap<>();
        for (final CountryData countryData : getCountries()) {
            countryDataMap.put(countryData.getIsocode(), countryData);
        }
        return countryDataMap;
    }

    @RequestMapping(value = "/addressform", method = RequestMethod.GET)
    public String getCountryAddressForm(@RequestParam("addressCode") final String addressCode,
            @RequestParam("countryIsoCode") final String countryIsoCode, final Model model) {
        model.addAttribute("supportedCountries", getCountries());
        model.addAttribute(REGIONS_ATTR, getI18NFacade().getRegionsForCountryIso(countryIsoCode));
        model.addAttribute(COUNTRY_ATTR, countryIsoCode);

        final AddressForm addressForm = new AddressForm();
        model.addAttribute(ADDRESS_FORM_ATTR, addressForm);
        for (final de.hybris.platform.commercefacades.user.data.AddressData addressData : userFacade
                .getAddressBook()) {

            if (addressData.getId() != null && addressData.getId().equals(addressCode)
                    && countryIsoCode.equals(addressData.getCountry().getIsocode())) {
                model.addAttribute(ADDRESS_DATA_ATTR, addressData);
                addressForm.setAddressId(addressData.getId());
                addressForm.setTitleCode(addressData.getTitleCode());
                addressForm.setFirstName(addressData.getFirstName());
                addressForm.setLastName(addressData.getLastName());
                addressForm.setLine1(addressData.getLine1());
                addressForm.setLine2(addressData.getLine2());
                addressForm.setTownCity(addressData.getTown());
                addressForm.setPostcode(addressData.getPostalCode());
                addressForm.setCountryIso(addressData.getCountry().getIsocode());
                addressForm.setPhone(addressData.getPhone());

                if (addressData.getRegion() != null && !StringUtils.isEmpty(addressData.getRegion().getIsocode())) {
                    addressForm.setRegionIso(addressData.getRegion().getIsocode());
                }

                break;
            }
        }
        return ControllerConstants.Views.Fragments.Account.CountryAddressForm;
    }

    @RequestMapping(method = RequestMethod.GET)
    @RequireHardLogIn
    public String account(final Model model, final RedirectAttributes redirectModel)
            throws CMSItemNotFoundException {
        if (ResponsiveUtils.isResponsive()) {
            GlobalMessages.addFlashMessage(redirectModel, GlobalMessages.ERROR_MESSAGES_HOLDER,
                    "system.error.page.not.found", null);
            return REDIRECT_PREFIX + "/";
        }
        storeCmsPageInModel(model, getContentPageForLabelOrId(ACCOUNT_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ACCOUNT_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(null));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    @RequestMapping(value = "/orders", method = RequestMethod.GET)
    @RequireHardLogIn
    public String orders(@RequestParam(value = "page", defaultValue = "0") final int page,
            @RequestParam(value = "show", defaultValue = "Page") final ShowMode showMode,
            @RequestParam(value = "sort", required = false) final String sortCode, final Model model)
            throws CMSItemNotFoundException {
        // Handle paged search results
        final PageableData pageableData = createPageableData(page, 5, sortCode, showMode);
        final SearchPageData<OrderHistoryData> searchPageData = orderFacade
                .getPagedOrderHistoryForStatuses(pageableData);
        populateModel(model, searchPageData, showMode);

        storeCmsPageInModel(model, getContentPageForLabelOrId(ORDER_HISTORY_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ORDER_HISTORY_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs("text.account.orderHistory"));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    @RequestMapping(value = "/order/" + ORDER_CODE_PATH_VARIABLE_PATTERN, method = RequestMethod.GET)
    @RequireHardLogIn
    public String order(@PathVariable("orderCode") final String orderCode, final Model model,
            final RedirectAttributes redirectModel) throws CMSItemNotFoundException {
        try {
            final OrderData orderDetails = orderFacade.getOrderDetailsForCode(orderCode);
            model.addAttribute("orderData", orderDetails);

            final List<Breadcrumb> breadcrumbs = accountBreadcrumbBuilder.getBreadcrumbs(null);
            breadcrumbs.add(new Breadcrumb("/my-account/orders", getMessageSource()
                    .getMessage("text.account.orderHistory", null, getI18nService().getCurrentLocale()), null));
            breadcrumbs.add(new Breadcrumb("#", getMessageSource().getMessage("text.account.order.orderBreadcrumb",
                    new Object[] { orderDetails.getCode() }, "Order {0}", getI18nService().getCurrentLocale()),
                    null));
            model.addAttribute(BREADCRUMBS_ATTR, breadcrumbs);

        } catch (final UnknownIdentifierException e) {
            LOG.warn("Attempted to load a order that does not exist or is not visible", e);
            GlobalMessages.addFlashMessage(redirectModel, GlobalMessages.ERROR_MESSAGES_HOLDER,
                    "system.error.page.not.found", null);
            return REDIRECT_TO_ORDER_HISTORY_PAGE;
        }
        storeCmsPageInModel(model, getContentPageForLabelOrId(ORDER_DETAIL_CMS_PAGE));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ORDER_DETAIL_CMS_PAGE));
        return getViewForPage(model);
    }

    @RequestMapping(value = "/order/" + ORDER_CODE_PATH_VARIABLE_PATTERN
            + "/getReadOnlyProductVariantMatrix", method = RequestMethod.GET)
    @RequireHardLogIn
    public String getProductVariantMatrixForResponsive(@PathVariable("orderCode") final String orderCode,
            @RequestParam("productCode") final String productCode, final Model model) {

        final ProductData productData = productFacade.getProductForCodeAndOptions(productCode,
                Arrays.asList(ProductOption.BASIC, ProductOption.CATEGORIES));
        final String baseProductCode = productData.getBaseProduct();

        final OrderData orderData = orderFacade.getOrderDetailsForCodeWithoutUser(orderCode);

        final Optional<OrderEntryData> orderEntryDataOptional = orderData.getEntries().stream()
                .filter(orderEntryData -> orderEntryData.getProduct().getCode().equals(baseProductCode))
                .findFirst();

        final Map<String, ReadOnlyOrderGridData> readOnlyMultiDMap = orderGridFormFacade
                .getReadOnlyOrderGrid(orderEntryDataOptional.get().getEntries());
        model.addAttribute("readOnlyMultiDMap", readOnlyMultiDMap);

        return ControllerConstants.Views.Fragments.Checkout.ReadOnlyExpandedOrderForm;
    }

    @RequestMapping(value = "/profile", method = RequestMethod.GET)
    @RequireHardLogIn
    public String profile(final Model model) throws CMSItemNotFoundException {
        final List<TitleData> titles = userFacade.getTitles();

        final CustomerData customerData = customCustomerFacade.getCurrentCustomer();
        if (customerData.getTitleCode() != null) {
            model.addAttribute("title", findTitleForCode(titles, customerData.getTitleCode()));
        }

        model.addAttribute("customerData", customerData);

        storeCmsPageInModel(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_PROFILE));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    protected TitleData findTitleForCode(final List<TitleData> titles, final String code) {
        if (code != null && !code.isEmpty() && titles != null && !titles.isEmpty()) {
            for (final TitleData title : titles) {
                if (code.equals(title.getCode())) {
                    return title;
                }
            }
        }
        return null;
    }

    @RequestMapping(value = "/update-email", method = RequestMethod.GET)
    @RequireHardLogIn
    public String editEmail(final Model model) throws CMSItemNotFoundException {
        final CustomerData customerData = customCustomerFacade.getCurrentCustomer();
        final UpdateEmailForm updateEmailForm = new UpdateEmailForm();

        updateEmailForm.setEmail(customerData.getDisplayUid());

        model.addAttribute("updateEmailForm", updateEmailForm);

        storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_EMAIL_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_EMAIL_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_PROFILE));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

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

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

        if (bindingResult.hasErrors()) {
            returnAction = setErrorMessagesAndCMSPage(model, UPDATE_EMAIL_CMS_PAGE);
        } else {
            try {
                customCustomerFacade.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 = customCustomerFacade.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 = setErrorMessagesAndCMSPage(model, UPDATE_EMAIL_CMS_PAGE);
            } catch (final PasswordMismatchException passwordMismatchException) {
                bindingResult.rejectValue("password", PROFILE_CURRENT_PASSWORD_INVALID);
                returnAction = setErrorMessagesAndCMSPage(model, UPDATE_EMAIL_CMS_PAGE);
            }
        }

        return returnAction;
    }

    protected String setErrorMessagesAndCMSPage(final Model model, final String cmsPageLabelOrId)
            throws CMSItemNotFoundException {
        GlobalMessages.addErrorMessage(model, FORM_GLOBAL_ERROR);
        storeCmsPageInModel(model, getContentPageForLabelOrId(cmsPageLabelOrId));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(cmsPageLabelOrId));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_PROFILE));
        return getViewForPage(model);
    }

    @RequestMapping(value = "/update-profile", method = RequestMethod.GET)
    @RequireHardLogIn
    public String editProfile(final Model model) throws CMSItemNotFoundException, ParseException {
        model.addAttribute(TITLE_DATA_ATTR, userFacade.getTitles());

        final CustomerData customerData = customCustomerFacade.getCurrentCustomer();
        final CustomUpdateProfileForm updateProfileForm = new CustomUpdateProfileForm();

        updateProfileForm.setTitleCode(customerData.getTitleCode());
        updateProfileForm.setFirstName(customerData.getFirstName());
        updateProfileForm.setLastName(customerData.getLastName());
        updateProfileForm.setBirthdate(customerData.getBirthdate());
        model.addAttribute("updateProfileForm", updateProfileForm);

        storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_PROFILE_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_PROFILE_CMS_PAGE));

        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_PROFILE));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    @RequestMapping(value = "/update-profile", method = RequestMethod.POST)
    @RequireHardLogIn
    public String updateProfile(final CustomUpdateProfileForm updateProfileForm, final BindingResult bindingResult,
            final Model model, final RedirectAttributes redirectAttributes) throws CMSItemNotFoundException {
        getProfileValidator().validate(updateProfileForm, bindingResult);

        String returnAction = REDIRECT_TO_UPDATE_PROFILE;
        final CustomerData currentCustomerData = customCustomerFacade.getCurrentCustomer();
        final CustomerData customerData = new CustomerData();
        customerData.setTitleCode(updateProfileForm.getTitleCode());
        customerData.setFirstName(updateProfileForm.getFirstName());
        customerData.setLastName(updateProfileForm.getLastName());
        customerData.setBirthdate(updateProfileForm.getBirthdate());
        customerData.setUid(currentCustomerData.getUid());
        customerData.setDisplayUid(currentCustomerData.getDisplayUid());

        model.addAttribute(TITLE_DATA_ATTR, userFacade.getTitles());

        storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_PROFILE_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_PROFILE_CMS_PAGE));

        if (bindingResult.hasErrors()) {
            returnAction = setErrorMessagesAndCMSPage(model, UPDATE_PROFILE_CMS_PAGE);
        } else {
            try {
                customCustomerFacade.updateProfile(customerData);
                GlobalMessages.addFlashMessage(redirectAttributes, GlobalMessages.CONF_MESSAGES_HOLDER,
                        "text.account.profile.confirmationUpdated", null);

            } catch (final DuplicateUidException e) {
                bindingResult.rejectValue("email", "registration.error.account.exists.title");
                returnAction = setErrorMessagesAndCMSPage(model, UPDATE_PROFILE_CMS_PAGE);
            }
        }

        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_PROFILE));
        return returnAction;
    }

    @RequestMapping(value = "/update-password", method = RequestMethod.GET)
    @RequireHardLogIn
    public String updatePassword(final Model model) throws CMSItemNotFoundException {
        final UpdatePasswordForm updatePasswordForm = new UpdatePasswordForm();

        model.addAttribute("updatePasswordForm", updatePasswordForm);

        storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_PASSWORD_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_PASSWORD_CMS_PAGE));

        model.addAttribute(BREADCRUMBS_ATTR,
                accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile.updatePasswordForm"));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    @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 {
                    customCustomerFacade.changePassword(updatePasswordForm.getCurrentPassword(),
                            updatePasswordForm.getNewPassword());
                } catch (final PasswordMismatchException localException) {
                    bindingResult.rejectValue("currentPassword", PROFILE_CURRENT_PASSWORD_INVALID, new Object[] {},
                            PROFILE_CURRENT_PASSWORD_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_ATTR,
                    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_PASSWORD_UPDATE_PAGE;
        }
    }

    @RequestMapping(value = "/address-book", method = RequestMethod.GET)
    @RequireHardLogIn
    public String getAddressBook(final Model model) throws CMSItemNotFoundException {
        model.addAttribute(ADDRESS_DATA_ATTR, userFacade.getAddressBook());

        storeCmsPageInModel(model, getContentPageForLabelOrId(ADDRESS_BOOK_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADDRESS_BOOK_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_ADDRESS_BOOK));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    @RequestMapping(value = "/wishlist", method = RequestMethod.GET)

    public String getWishlist(final Model model,
            @RequestParam(value = "show", defaultValue = "Page") final ShowMode showMode)
            throws CMSItemNotFoundException {

        final List<ProductModel> searchPageData = wishlistFacade.getWishlist();

        model.addAttribute("searchPageData", productWishlistFacade.convertWishlistToProductData(searchPageData));
        storeCmsPageInModel(model, getContentPageForLabelOrId(WISHLIST_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(WISHLIST_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR, accountBreadcrumbBuilder.getBreadcrumbs(TEXT_ACCOUNT_WISHLIST));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);

        return ControllerConstants.Views.Pages.Account.AccountWishlistPage;
    }

    @RequestMapping(value = "/add-address", method = RequestMethod.GET)
    @RequireHardLogIn
    public String addAddress(final Model model) throws CMSItemNotFoundException {
        model.addAttribute(COUNTRY_DATA_ATTR, checkoutFacade.getDeliveryCountries());
        model.addAttribute(TITLE_DATA_ATTR, userFacade.getTitles());
        final AddressForm addressForm = getPreparedAddressForm();
        model.addAttribute(ADDRESS_FORM_ATTR, addressForm);
        model.addAttribute(ADDRESS_BOOK_EMPTY_ATTR, Boolean.valueOf(userFacade.isAddressBookEmpty()));
        model.addAttribute(IS_DEFAULT_ADDRESS_ATTR, Boolean.FALSE);
        storeCmsPageInModel(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));

        final List<Breadcrumb> breadcrumbs = accountBreadcrumbBuilder.getBreadcrumbs(null);
        breadcrumbs.add(new Breadcrumb(MY_ACCOUNT_ADDRESS_BOOK_URL,
                getMessageSource().getMessage(TEXT_ACCOUNT_ADDRESS_BOOK, null, getI18nService().getCurrentLocale()),
                null));
        breadcrumbs.add(new Breadcrumb("#", getMessageSource().getMessage("text.account.addressBook.addEditAddress",
                null, getI18nService().getCurrentLocale()), null));
        model.addAttribute(BREADCRUMBS_ATTR, breadcrumbs);
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    protected AddressForm getPreparedAddressForm() {
        final CustomerData currentCustomerData = customCustomerFacade.getCurrentCustomer();
        final AddressForm addressForm = new AddressForm();
        addressForm.setFirstName(currentCustomerData.getFirstName());
        addressForm.setLastName(currentCustomerData.getLastName());
        addressForm.setTitleCode(currentCustomerData.getTitleCode());
        return addressForm;
    }

    @RequestMapping(value = "/add-address", method = RequestMethod.POST)
    @RequireHardLogIn
    public String addAddress(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);
        }

        final AddressData newAddress = new AddressData();
        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()));
        newAddress.setPhone(addressForm.getPhone());

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

        if (userFacade.isAddressBookEmpty()) {
            newAddress.setDefaultAddress(true);
            newAddress.setVisibleInAddressBook(true);
        } else {
            newAddress.setDefaultAddress(
                    addressForm.getDefaultAddress() != null && addressForm.getDefaultAddress().booleanValue());
        }

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

        model.addAttribute(REGIONS_ATTR, getI18NFacade().getRegionsForCountryIso(addressForm.getCountryIso()));
        model.addAttribute(COUNTRY_ATTR, addressForm.getCountryIso());
        model.addAttribute("edit", Boolean.TRUE);
        model.addAttribute(IS_DEFAULT_ADDRESS_ATTR, Boolean.valueOf(isDefaultAddress(addressForm.getAddressId())));

        if (addressRequiresReview) {
            storeCmsPageInModel(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
            setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
            return getViewForPage(model);
        }

        userFacade.addAddress(newAddress);

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

        return REDIRECT_TO_EDIT_ADDRESS_PAGE + newAddress.getId();
    }

    protected void setUpAddressFormAfterError(final AddressForm addressForm, final Model model) {
        model.addAttribute(COUNTRY_DATA_ATTR, checkoutFacade.getDeliveryCountries());
        model.addAttribute(TITLE_DATA_ATTR, userFacade.getTitles());
        model.addAttribute(ADDRESS_BOOK_EMPTY_ATTR, Boolean.valueOf(userFacade.isAddressBookEmpty()));
        model.addAttribute(IS_DEFAULT_ADDRESS_ATTR, Boolean.valueOf(isDefaultAddress(addressForm.getAddressId())));
        if (addressForm.getCountryIso() != null) {
            model.addAttribute(REGIONS_ATTR, getI18NFacade().getRegionsForCountryIso(addressForm.getCountryIso()));
            model.addAttribute(COUNTRY_ATTR, addressForm.getCountryIso());
        }
    }

    @RequestMapping(value = "/edit-address/" + ADDRESS_CODE_PATH_VARIABLE_PATTERN, method = RequestMethod.GET)
    @RequireHardLogIn
    public String editAddress(@PathVariable("addressCode") final String addressCode, final Model model)
            throws CMSItemNotFoundException {
        final AddressForm addressForm = new AddressForm();
        model.addAttribute(COUNTRY_DATA_ATTR, checkoutFacade.getDeliveryCountries());
        model.addAttribute(TITLE_DATA_ATTR, userFacade.getTitles());
        model.addAttribute(ADDRESS_FORM_ATTR, addressForm);
        final List<de.hybris.platform.commercefacades.user.data.AddressData> addressBook = userFacade
                .getAddressBook();
        model.addAttribute(ADDRESS_BOOK_EMPTY_ATTR, Boolean.valueOf(CollectionUtils.isEmpty(addressBook)));

        for (final AddressData addressData : addressBook) {
            if (addressData.getId() != null && addressData.getId().equals(addressCode)) {
                model.addAttribute(REGIONS_ATTR,
                        getI18NFacade().getRegionsForCountryIso(addressData.getCountry().getIsocode()));
                model.addAttribute(COUNTRY_ATTR, addressData.getCountry().getIsocode());
                model.addAttribute(ADDRESS_DATA_ATTR, addressData);
                addressForm.setAddressId(addressData.getId());
                addressForm.setTitleCode(addressData.getTitleCode());
                addressForm.setFirstName(addressData.getFirstName());
                addressForm.setLastName(addressData.getLastName());
                addressForm.setLine1(addressData.getLine1());
                addressForm.setLine2(addressData.getLine2());
                addressForm.setTownCity(addressData.getTown());
                addressForm.setPostcode(addressData.getPostalCode());
                addressForm.setCountryIso(addressData.getCountry().getIsocode());
                addressForm.setPhone(addressData.getPhone());

                if (addressData.getRegion() != null && !StringUtils.isEmpty(addressData.getRegion().getIsocode())) {
                    addressForm.setRegionIso(addressData.getRegion().getIsocode());
                }

                if (isDefaultAddress(addressData.getId())) {
                    addressForm.setDefaultAddress(Boolean.TRUE);
                    model.addAttribute(IS_DEFAULT_ADDRESS_ATTR, Boolean.TRUE);
                } else {
                    addressForm.setDefaultAddress(Boolean.FALSE);
                    model.addAttribute(IS_DEFAULT_ADDRESS_ATTR, Boolean.FALSE);
                }
                break;
            }
        }

        storeCmsPageInModel(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));

        final List<Breadcrumb> breadcrumbs = accountBreadcrumbBuilder.getBreadcrumbs(null);
        breadcrumbs.add(new Breadcrumb(MY_ACCOUNT_ADDRESS_BOOK_URL,
                getMessageSource().getMessage(TEXT_ACCOUNT_ADDRESS_BOOK, null, getI18nService().getCurrentLocale()),
                null));
        breadcrumbs.add(new Breadcrumb("#", getMessageSource().getMessage("text.account.addressBook.addEditAddress",
                null, getI18nService().getCurrentLocale()), null));
        model.addAttribute(BREADCRUMBS_ATTR, breadcrumbs);
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        model.addAttribute("edit", Boolean.TRUE);
        return getViewForPage(model);
    }

    /**
     * Method checks if address is set as default
     *
     * @param addressId
     *           - identifier for address to check
     * @return true if address is default, false if address is not default
     */
    protected boolean isDefaultAddress(final String addressId) {
        final AddressData defaultAddress = userFacade.getDefaultAddress();
        return defaultAddress != null && defaultAddress.getId() != null && defaultAddress.getId().equals(addressId);
    }

    @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(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.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()));
        newAddress.setPhone(addressForm.getPhone());

        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");

        model.addAttribute(REGIONS_ATTR, getI18NFacade().getRegionsForCountryIso(addressForm.getCountryIso()));
        model.addAttribute(COUNTRY_ATTR, addressForm.getCountryIso());
        model.addAttribute("edit", Boolean.TRUE);
        model.addAttribute(IS_DEFAULT_ADDRESS_ATTR, Boolean.valueOf(isDefaultAddress(addressForm.getAddressId())));

        if (addressRequiresReview) {
            storeCmsPageInModel(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
            setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
            return getViewForPage(model);
        }

        userFacade.editAddress(newAddress);

        GlobalMessages.addFlashMessage(redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER,
                "account.confirmation.address.updated", null);
        return REDIRECT_TO_EDIT_ADDRESS_PAGE + newAddress.getId();
    }

    @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);
        selectedAddress.setPhone(addressForm.getPhone());

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

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

        if (resolveCountryRegions.contains(countryData.getIsocode()) && 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 = "/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 = "/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;
    }

    @RequestMapping(value = "/payment-details", method = RequestMethod.GET)
    @RequireHardLogIn
    public String paymentDetails(final Model model) throws CMSItemNotFoundException {
        model.addAttribute("customerData", customCustomerFacade.getCurrentCustomer());
        model.addAttribute("paymentInfoData", userFacade.getCCPaymentInfos(true));
        storeCmsPageInModel(model, getContentPageForLabelOrId(PAYMENT_DETAILS_CMS_PAGE));
        setUpMetaDataForContentPage(model, getContentPageForLabelOrId(ADD_EDIT_ADDRESS_CMS_PAGE));
        model.addAttribute(BREADCRUMBS_ATTR,
                accountBreadcrumbBuilder.getBreadcrumbs("text.account.paymentDetails"));
        model.addAttribute(ThirdPartyConstants.SeoRobots.META_ROBOTS,
                ThirdPartyConstants.SeoRobots.NOINDEX_NOFOLLOW);
        return getViewForPage(model);
    }

    @RequestMapping(value = "/set-default-payment-details", method = RequestMethod.POST)
    @RequireHardLogIn
    public String setDefaultPaymentDetails(@RequestParam final String paymentInfoId) {
        CCPaymentInfoData paymentInfoData = null;
        if (StringUtils.isNotBlank(paymentInfoId)) {
            paymentInfoData = userFacade.getCCPaymentInfoForCode(paymentInfoId);
        }
        userFacade.setDefaultPaymentInfo(paymentInfoData);
        return REDIRECT_TO_PAYMENT_INFO_PAGE;
    }

    @RequestMapping(value = "/remove-payment-method", method = RequestMethod.POST)
    @RequireHardLogIn
    public String removePaymentMethod(@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;
    }
}