com.epam.trade.storefront.controllers.pages.ProductPageController.java Source code

Java tutorial

Introduction

Here is the source code for com.epam.trade.storefront.controllers.pages.ProductPageController.java

Source

/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2015 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 com.epam.trade.storefront.controllers.pages;

import de.hybris.platform.acceleratorservices.controllers.page.PageType;
import de.hybris.platform.acceleratorstorefrontcommons.breadcrumb.impl.ProductBreadcrumbBuilder;
import de.hybris.platform.acceleratorstorefrontcommons.constants.WebConstants;
import de.hybris.platform.acceleratorstorefrontcommons.controllers.pages.AbstractPageController;
import de.hybris.platform.acceleratorstorefrontcommons.util.XSSFilterUtil;
import de.hybris.platform.acceleratorstorefrontcommons.variants.VariantSortStrategy;
import de.hybris.platform.catalog.enums.ProductReferenceTypeEnum;
import de.hybris.platform.cms2.exceptions.CMSItemNotFoundException;
import de.hybris.platform.cms2.model.pages.AbstractPageModel;
import de.hybris.platform.cms2.servicelayer.services.CMSPageService;
import de.hybris.platform.commercefacades.product.ProductFacade;
import de.hybris.platform.commercefacades.product.ProductOption;
import de.hybris.platform.commercefacades.product.data.BaseOptionData;
import de.hybris.platform.commercefacades.product.data.ImageData;
import de.hybris.platform.commercefacades.product.data.ImageDataType;
import de.hybris.platform.commercefacades.product.data.ProductData;
import de.hybris.platform.commercefacades.product.data.ProductReferenceData;
import de.hybris.platform.commerceservices.url.UrlResolver;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.product.ProductService;
import de.hybris.platform.servicelayer.user.UserService;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

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.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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.bind.annotation.ResponseBody;

import com.epam.trade.facades.advertisement.AdvertisementFacade;
import com.epam.trade.facades.comment.CustomerCommentFacade;
import com.epam.trade.facades.product.CommentData;
import com.epam.trade.storefront.controllers.ControllerConstants;
import com.epam.trade.storefront.forms.CommentForm;
import com.epam.trade.storefront.forms.validation.CommentValidator;
import com.epam.trade.storefront.util.MetaSanitizerUtil;
import com.granule.json.JSONException;
import com.granule.json.JSONObject;

/**
 * Controller for product details page
 */
@Controller
@Scope("tenant")
@RequestMapping(value = "/**/p")
public class ProductPageController extends AbstractPageController {
    @SuppressWarnings("unused")
    private static final Logger LOG = Logger.getLogger(ProductPageController.class);

    /**
     * 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 PRODUCT_CODE_PATH_VARIABLE_PATTERN = "/{productCode:.*}";

    @Resource(name = "productModelUrlResolver")
    private UrlResolver<ProductModel> productModelUrlResolver;

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

    @Resource(name = "productService")
    private ProductService productService;

    @Resource(name = "productBreadcrumbBuilder")
    private ProductBreadcrumbBuilder productBreadcrumbBuilder;

    @Resource(name = "cmsPageService")
    private CMSPageService cmsPageService;

    @Resource(name = "userService")
    private UserService userService;

    @Resource(name = "variantSortStrategy")
    private VariantSortStrategy variantSortStrategy;

    @Resource(name = "commentValidator")
    private CommentValidator commentValidator;

    @Resource(name = "customerCommentFacade")
    private CustomerCommentFacade customerCommentFacade;

    @Resource(name = "defaultAdvertisementFacade")
    private AdvertisementFacade advertisementFacade;

    @RequestMapping(value = PRODUCT_CODE_PATH_VARIABLE_PATTERN, method = RequestMethod.GET)
    public String productDetail(@PathVariable("productCode") final String productCode, final Model model,
            final HttpServletRequest request, final HttpServletResponse response)
            throws CMSItemNotFoundException, UnsupportedEncodingException {
        final ProductModel productModel = productService.getProductForCode(productCode);
        final String redirection = checkRequestUrl(request, response,
                productModelUrlResolver.resolve(productModel));
        if (StringUtils.isNotEmpty(redirection)) {
            return redirection;
        }

        updatePageTitle(productModel, model);
        populateProductDetailForDisplay(productModel, model, request);
        model.addAttribute(new CommentForm());
        final List<ProductReferenceData> productReferences = productFacade.getProductReferencesForCode(productCode,
                Arrays.asList(ProductReferenceTypeEnum.SIMILAR, ProductReferenceTypeEnum.ACCESSORIES),
                Arrays.asList(ProductOption.BASIC, ProductOption.PRICE), null);
        model.addAttribute("productReferences", productReferences);
        model.addAttribute("pageType", PageType.PRODUCT.name());
        model.addAttribute("comments", customerCommentFacade.getAllComments(productCode));

        if (isMyAdvertisement(productModel)) {
            final String contactNumber = advertisementFacade.getContactNumberByAdvertisementCode(productCode);
            final HttpSession session = request.getSession();
            session.setAttribute("phoneNumberForCode", productCode);
            session.setAttribute("openedPhoneNumber", contactNumber);
        }

        final String metaKeywords = MetaSanitizerUtil.sanitizeKeywords(productModel.getKeywords());
        final String metaDescription = MetaSanitizerUtil.sanitizeDescription(productModel.getDescription());
        setUpMetaData(model, metaKeywords, metaDescription);
        return getViewForPage(model);
    }

    private boolean isMyAdvertisement(final ProductModel productModel) {
        return userService.getCurrentUser().getAdvertisement().contains(productModel);
    }

    @RequestMapping(value = PRODUCT_CODE_PATH_VARIABLE_PATTERN + "/zoomImages", method = RequestMethod.GET)
    public String showZoomImages(@PathVariable("productCode") final String productCode,
            @RequestParam(value = "galleryPosition", required = false) final String galleryPosition,
            final Model model) {
        final ProductModel productModel = productService.getProductForCode(productCode);
        final ProductData productData = productFacade.getProductForOptions(productModel,
                Collections.singleton(ProductOption.GALLERY));
        final List<Map<String, ImageData>> images = getGalleryImages(productData);
        populateProductData(productData, model);
        if (galleryPosition != null) {
            try {
                model.addAttribute("zoomImageUrl",
                        images.get(Integer.parseInt(galleryPosition)).get("zoom").getUrl());
            } catch (final IndexOutOfBoundsException | NumberFormatException ioebe) {
                model.addAttribute("zoomImageUrl", "");
            }
        }
        return ControllerConstants.Views.Fragments.Product.ZoomImagesPopup;
    }

    @RequestMapping(value = PRODUCT_CODE_PATH_VARIABLE_PATTERN + "/quickView", method = RequestMethod.GET)
    public String showQuickView(@PathVariable("productCode") final String productCode, final Model model,
            final HttpServletRequest request) {
        final ProductModel productModel = productService.getProductForCode(productCode);
        final ProductData productData = productFacade.getProductForOptions(productModel,
                Arrays.asList(ProductOption.BASIC, ProductOption.PRICE, ProductOption.SUMMARY,
                        ProductOption.DESCRIPTION, ProductOption.CATEGORIES, ProductOption.PROMOTIONS,
                        ProductOption.STOCK, ProductOption.REVIEW, ProductOption.VARIANT_FULL,
                        ProductOption.DELIVERY_MODE_AVAILABILITY));

        sortVariantOptionData(productData);
        populateProductData(productData, model);
        getRequestContextData(request).setProduct(productModel);

        return ControllerConstants.Views.Fragments.Product.QuickViewPopup;
    }

    @RequestMapping(value = "/postComment", method = RequestMethod.POST)
    public @ResponseBody String postComment(@RequestParam("productCode") final String productCode,
            @RequestParam("commentText") final String commentText, final CommentForm form,
            final BindingResult result) throws JSONException {
        form.setComment(commentText);
        getCommentValidator().validate(form, result);
        CommentData savedComment = null;

        if (!result.hasErrors()) {
            final CommentData comment = new CommentData();
            comment.setBody(XSSFilterUtil.filter(form.getComment()));
            savedComment = customerCommentFacade.postComment(productCode, comment);
        }

        final Map<String, Object> jsonResult = new HashMap<String, Object>();
        jsonResult.put("comment", savedComment);
        jsonResult.put("hasErrors", result.hasErrors());
        final JSONObject json = new JSONObject(jsonResult);
        return json.toString();
    }

    @RequestMapping(value = "/remove", method = RequestMethod.GET)
    public @ResponseBody String removeOwnComment(@RequestParam("commentCode") final String commentCode) {
        customerCommentFacade.removeCommentByCode(commentCode);
        return "comment.confirmation.remove.title";
    }

    @RequestMapping(value = "/showPhoneNumber", method = RequestMethod.GET)
    public @ResponseBody String showPhoneNumber(@RequestParam("advertisementCode") final String advertisementCode,
            final HttpServletRequest request) {
        advertisementFacade.addViewedPhoneNumbersAdvertisement(advertisementCode);
        final String contactNumber = advertisementFacade.getContactNumberByAdvertisementCode(advertisementCode);

        final HttpSession session = request.getSession();
        session.setAttribute("phoneNumberForCode", advertisementCode);
        session.setAttribute("openedPhoneNumber", contactNumber);

        return contactNumber;
    }

    protected void updatePageTitle(final ProductModel productModel, final Model model) {
        storeContentPageTitleInModel(model, getPageTitleResolver().resolveProductPageTitle(productModel));
    }

    protected void populateProductDetailForDisplay(final ProductModel productModel, final Model model,
            final HttpServletRequest request) throws CMSItemNotFoundException {
        getRequestContextData(request).setProduct(productModel);

        final ProductData productData = productFacade.getProductForOptions(productModel,
                Arrays.asList(ProductOption.BASIC, ProductOption.PRICE, ProductOption.SUMMARY,
                        ProductOption.DESCRIPTION, ProductOption.GALLERY, ProductOption.CATEGORIES,
                        ProductOption.REVIEW, ProductOption.PROMOTIONS, ProductOption.CLASSIFICATION,
                        ProductOption.VARIANT_FULL, ProductOption.STOCK, ProductOption.VOLUME_PRICES,
                        ProductOption.DELIVERY_MODE_AVAILABILITY));

        sortVariantOptionData(productData);
        storeCmsPageInModel(model, getPageForProduct(productModel));
        populateProductData(productData, model);
        model.addAttribute(WebConstants.BREADCRUMBS_KEY, productBreadcrumbBuilder.getBreadcrumbs(productModel));
    }

    protected void populateProductData(final ProductData productData, final Model model) {
        model.addAttribute("galleryImages", getGalleryImages(productData));
        model.addAttribute("product", productData);
    }

    protected void sortVariantOptionData(final ProductData productData) {
        if (CollectionUtils.isNotEmpty(productData.getBaseOptions())) {
            for (final BaseOptionData baseOptionData : productData.getBaseOptions()) {
                if (CollectionUtils.isNotEmpty(baseOptionData.getOptions())) {
                    Collections.sort(baseOptionData.getOptions(), variantSortStrategy);
                }
            }
        }

        if (CollectionUtils.isNotEmpty(productData.getVariantOptions())) {
            Collections.sort(productData.getVariantOptions(), variantSortStrategy);
        }
    }

    protected List<Map<String, ImageData>> getGalleryImages(final ProductData productData) {
        final List<Map<String, ImageData>> galleryImages = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(productData.getImages())) {
            final List<ImageData> images = new ArrayList<>();
            for (final ImageData image : productData.getImages()) {
                if (ImageDataType.GALLERY.equals(image.getImageType())) {
                    images.add(image);
                }
            }
            Collections.sort(images, new Comparator<ImageData>() {
                @Override
                public int compare(final ImageData image1, final ImageData image2) {
                    return image1.getGalleryIndex().compareTo(image2.getGalleryIndex());
                }
            });

            if (CollectionUtils.isNotEmpty(images)) {
                int currentIndex = images.get(0).getGalleryIndex().intValue();
                Map<String, ImageData> formats = new HashMap<String, ImageData>();
                for (final ImageData image : images) {
                    if (currentIndex != image.getGalleryIndex().intValue()) {
                        galleryImages.add(formats);
                        formats = new HashMap<>();
                        currentIndex = image.getGalleryIndex().intValue();
                    }
                    formats.put(image.getFormat(), image);
                }
                if (!formats.isEmpty()) {
                    galleryImages.add(formats);
                }
            }
        }
        return galleryImages;
    }

    protected CommentValidator getCommentValidator() {
        return commentValidator;
    }

    protected AbstractPageModel getPageForProduct(final ProductModel product) throws CMSItemNotFoundException {
        return cmsPageService.getPageForProduct(product);
    }

}