Java tutorial
/* * [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); } }