Java tutorial
/* * [y] hybris Platform * * Copyright (c) 2000-2016 SAP SE or an SAP affiliate company. * All rights reserved. * * This software is the confidential and proprietary information of SAP * ("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 SAP. */ package com.ctc.storefront.controllers.misc; import de.hybris.platform.acceleratorfacades.product.data.ProductWrapperData; import de.hybris.platform.acceleratorservices.config.SiteConfigService; import de.hybris.platform.acceleratorstorefrontcommons.controllers.AbstractController; import de.hybris.platform.acceleratorstorefrontcommons.forms.AddToCartForm; import de.hybris.platform.acceleratorstorefrontcommons.forms.AddToCartOrderForm; import de.hybris.platform.commercefacades.order.CartFacade; import de.hybris.platform.commercefacades.order.converters.populator.GroupCartModificationListPopulator; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.order.data.CartModificationData; import de.hybris.platform.commercefacades.order.data.OrderEntryData; 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.commerceservices.order.CommerceCartModificationException; import de.hybris.platform.util.Config; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.annotation.Resource; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.ctc.storefront.controllers.ControllerConstants; /** * Controller for Add to Cart functionality which is not specific to a certain page. */ @Controller public class AddToCartController extends AbstractController { private static final String QUANTITY_ATTR = "quantity"; private static final String TYPE_MISMATCH_ERROR_CODE = "typeMismatch"; private static final String ERROR_MSG_TYPE = "errorMsg"; private static final String QUANTITY_INVALID_BINDING_MESSAGE_KEY = "basket.error.quantity.invalid.binding"; private static final String SHOWN_PRODUCT_COUNT = "ctcstorefront.storefront.minicart.shownProductCount"; private static final String REDIRECT_CART_URL = REDIRECT_PREFIX + "/cart"; public static final String CART_COUNT_COOKIE_DOMAIN_NAME = "cart.count.cookie.domain.name"; private static final Logger LOG = Logger.getLogger(AddToCartController.class); @Resource(name = "cartFacade") private CartFacade cartFacade; @Resource(name = "accProductFacade") private ProductFacade productFacade; @Resource(name = "groupCartModificationListPopulator") private GroupCartModificationListPopulator groupCartModificationListPopulator; @Resource(name = "siteConfigService") private SiteConfigService siteConfigService; @RequestMapping(value = "/cart/add", method = RequestMethod.POST, produces = "application/json") public String addToCart(@RequestParam("productCodePost") final String code, final Model model, @Valid final AddToCartForm form, final BindingResult bindingErrors, final HttpServletResponse response) { if (bindingErrors.hasErrors()) { return getViewWithBindingErrorMessages(model, bindingErrors); } final long qty = form.getQty(); if (qty <= 0) { model.addAttribute(ERROR_MSG_TYPE, "basket.error.quantity.invalid"); model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L)); } else { try { final CartModificationData cartModification = cartFacade.addToCart(code, qty); model.addAttribute(QUANTITY_ATTR, Long.valueOf(cartModification.getQuantityAdded())); model.addAttribute("entry", cartModification.getEntry()); model.addAttribute("cartCode", cartModification.getCartCode()); if (cartModification.getQuantityAdded() == 0L) { model.addAttribute(ERROR_MSG_TYPE, "basket.information.quantity.noItemsAdded." + cartModification.getStatusCode()); } else if (cartModification.getQuantityAdded() < qty) { model.addAttribute(ERROR_MSG_TYPE, "basket.information.quantity.reducedNumberOfItemsAdded." + cartModification.getStatusCode()); } setCookie(response, cartFacade.getSessionCart()); } catch (final CommerceCartModificationException ex) { logDebugException(ex); model.addAttribute(ERROR_MSG_TYPE, "basket.error.occurred"); model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L)); } } model.addAttribute("product", productFacade.getProductForCodeAndOptions(code, Arrays.asList(ProductOption.BASIC))); return ControllerConstants.Views.Fragments.Cart.AddToCartPopup; } protected String getViewWithBindingErrorMessages(final Model model, final BindingResult bindingErrors) { for (final ObjectError error : bindingErrors.getAllErrors()) { if (isTypeMismatchError(error)) { model.addAttribute(ERROR_MSG_TYPE, QUANTITY_INVALID_BINDING_MESSAGE_KEY); } else { model.addAttribute(ERROR_MSG_TYPE, error.getDefaultMessage()); } } return ControllerConstants.Views.Fragments.Cart.AddToCartPopup; } protected boolean isTypeMismatchError(final ObjectError error) { return error.getCode().equals(TYPE_MISMATCH_ERROR_CODE); } @RequestMapping(value = "/cart/addGrid", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public final String addGridToCart(@RequestBody final AddToCartOrderForm form, final Model model) { final Set<String> multidErrorMsgs = new HashSet<String>(); final List<CartModificationData> modificationDataList = new ArrayList<CartModificationData>(); for (final OrderEntryData cartEntry : form.getCartEntries()) { if (!isValidProductEntry(cartEntry)) { LOG.error("Error processing entry"); } else if (!isValidQuantity(cartEntry)) { multidErrorMsgs.add("basket.error.quantity.invalid"); } else { final String errorMsg = addEntryToCart(modificationDataList, cartEntry, true); if (StringUtils.isNotEmpty(errorMsg)) { multidErrorMsgs.add(errorMsg); } } } if (CollectionUtils.isNotEmpty(modificationDataList)) { groupCartModificationListPopulator.populate(null, modificationDataList); model.addAttribute("modifications", modificationDataList); } if (CollectionUtils.isNotEmpty(multidErrorMsgs)) { model.addAttribute("multidErrorMsgs", multidErrorMsgs); } model.addAttribute("numberShowing", Integer.valueOf(Config.getInt(SHOWN_PRODUCT_COUNT, 3))); return ControllerConstants.Views.Fragments.Cart.AddToCartPopup; } @RequestMapping(value = "/cart/addQuickOrder", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public final String addQuickOrderToCart(@RequestBody final AddToCartOrderForm form, final Model model) { final List<CartModificationData> modificationDataList = new ArrayList(); final List<ProductWrapperData> productWrapperDataList = new ArrayList(); final int maxQuickOrderEntries = Config.getInt("ctcstorefront.quick.order.rows.max", 25); final int sizeOfCartEntries = CollectionUtils.size(form.getCartEntries()); form.getCartEntries().stream().limit(Math.min(sizeOfCartEntries, maxQuickOrderEntries)) .forEach(cartEntry -> { String errorMsg = StringUtils.EMPTY; final String sku = !isValidProductEntry(cartEntry) ? StringUtils.EMPTY : cartEntry.getProduct().getCode(); if (StringUtils.isEmpty(sku)) { errorMsg = "text.quickOrder.product.code.invalid"; } else if (!isValidQuantity(cartEntry)) { errorMsg = "text.quickOrder.product.quantity.invalid"; } else { errorMsg = addEntryToCart(modificationDataList, cartEntry, false); } if (StringUtils.isNotEmpty(errorMsg)) { productWrapperDataList.add(createProductWrapperData(sku, errorMsg)); } }); if (CollectionUtils.isNotEmpty(productWrapperDataList)) { model.addAttribute("quickOrderErrorData", productWrapperDataList); model.addAttribute("quickOrderErrorMsg", "basket.quick.order.error"); } if (CollectionUtils.isNotEmpty(modificationDataList)) { model.addAttribute("modifications", modificationDataList); } return ControllerConstants.Views.Fragments.Cart.AddToCartPopup; } protected ProductWrapperData createProductWrapperData(final String sku, final String errorMsg) { final ProductWrapperData productWrapperData = new ProductWrapperData(); final ProductData productData = new ProductData(); productData.setCode(sku); productWrapperData.setProductData(productData); productWrapperData.setErrorMsg(errorMsg); return productWrapperData; } protected void logDebugException(final Exception ex) { if (LOG.isDebugEnabled()) { LOG.debug(ex); } } protected String addEntryToCart(final List<CartModificationData> modificationDataList, final OrderEntryData cartEntry, final boolean isReducedQtyError) { String errorMsg = StringUtils.EMPTY; try { final long qty = cartEntry.getQuantity().longValue(); final CartModificationData cartModificationData = cartFacade.addToCart(cartEntry.getProduct().getCode(), qty); if (cartModificationData.getQuantityAdded() == 0L) { errorMsg = "basket.information.quantity.noItemsAdded." + cartModificationData.getStatusCode(); } else if (cartModificationData.getQuantityAdded() < qty && isReducedQtyError) { errorMsg = "basket.information.quantity.reducedNumberOfItemsAdded." + cartModificationData.getStatusCode(); } modificationDataList.add(cartModificationData); } catch (final CommerceCartModificationException ex) { errorMsg = "basket.error.occurred"; logDebugException(ex); } return errorMsg; } protected boolean isValidProductEntry(final OrderEntryData cartEntry) { return cartEntry.getProduct() != null && StringUtils.isNotBlank(cartEntry.getProduct().getCode()); } protected boolean isValidQuantity(final OrderEntryData cartEntry) { return cartEntry.getQuantity() != null && cartEntry.getQuantity().longValue() >= 1L; } @RequestMapping(value = "/cart/add", method = RequestMethod.POST, params = { "buyNow" }) public String buyNow(@RequestParam("productCodePost") final String code, final Model model, @Valid final AddToCartForm form, final BindingResult bindingErrors, final HttpServletResponse response) { if (bindingErrors.hasErrors()) { return getViewWithBindingErrorMessages(model, bindingErrors); } final long qty = form.getQty(); if (qty <= 0) { model.addAttribute(ERROR_MSG_TYPE, "basket.error.quantity.invalid"); model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L)); } else { try { final CartModificationData cartModification = cartFacade.addToCart(code, qty); if (cartModification.getQuantityAdded() == 0L) { model.addAttribute(ERROR_MSG_TYPE, "basket.information.quantity.noItemsAdded." + cartModification.getStatusCode()); } else if (cartModification.getQuantityAdded() < qty) { model.addAttribute(ERROR_MSG_TYPE, "basket.information.quantity.reducedNumberOfItemsAdded." + cartModification.getStatusCode()); } setCookie(response, cartFacade.getSessionCart()); } catch (final CommerceCartModificationException ex) { logDebugException(ex); model.addAttribute(ERROR_MSG_TYPE, "basket.error.occurred"); model.addAttribute(QUANTITY_ATTR, Long.valueOf(0L)); } } return REDIRECT_CART_URL; } private void setCookie(final HttpServletResponse response, final CartData cartData) { final Cookie cookie = new Cookie("cartQuantity", String.valueOf(cartData.getTotalUnitCount())); cookie.setMaxAge(60 * 60); cookie.setPath("/"); cookie.setDomain(siteConfigService.getString(CART_COUNT_COOKIE_DOMAIN_NAME, ".ctc.com")); response.addCookie(cookie); } }