PerfectPartnerPromotionHandler.java 14.2 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.i18n.I18n
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.api.PageManager
 *  javax.servlet.http.HttpServletRequest
 *  org.apache.commons.collections.Predicate
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ResourceResolverFactory
 *  org.apache.sling.api.resource.ResourceUtil
 *  org.apache.sling.api.resource.ValueMap
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.commerce.common.promotion;

import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.CommerceSession;
import com.adobe.cq.commerce.api.PriceInfo;
import com.adobe.cq.commerce.api.Product;
import com.adobe.cq.commerce.api.promotion.Promotion;
import com.adobe.cq.commerce.api.promotion.PromotionHandler;
import com.adobe.cq.commerce.common.CommerceHelper;
import com.adobe.cq.commerce.common.PriceFilter;
import com.day.cq.i18n.I18n;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.collections.Predicate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Deprecated
public class PerfectPartnerPromotionHandler
implements PromotionHandler {
    private final Logger log = LoggerFactory.getLogger(PerfectPartnerPromotionHandler.class);
    @Reference
    private ResourceResolverFactory resolverFactory = null;
    Map<String, PairingsCache> promoCache = new HashMap<String, PairingsCache>();

    private PriceInfo calcDiscount(CommerceSession.CartEntry cartEntry, String discountType, BigDecimal discountValue) throws CommerceException {
        BigDecimal discount = BigDecimal.ZERO;
        PriceInfo unitPrice = cartEntry.getPriceInfo(new PriceFilter("UNIT")).get(0);
        if (discountType.equals("percentage")) {
            discount = discount.add(unitPrice.getAmount().multiply(discountValue.divide(new BigDecimal(100.0))));
        } else if (discountType.equals("absolute")) {
            discount = discount.add(discountValue);
        }
        discount = discount.multiply(new BigDecimal(cartEntry.getQuantity()));
        return new PriceInfo(discount, unitPrice.getLocale());
    }

    @Override
    public synchronized PriceInfo applyCartEntryPromotion(CommerceSession commerceSession, Promotion promotion, CommerceSession.CartEntry cartEntry) throws CommerceException {
        ValueMap config = promotion.getConfig();
        String discountType = (String)config.get("discountType", (Object)"");
        BigDecimal discountValue = (BigDecimal)config.get("discountValue", (Object)BigDecimal.ZERO);
        String promoPath = promotion.getPath();
        this.validateCache(promoPath);
        if (this.promoCache.get(promoPath).getCompanion(cartEntry.getProduct(), commerceSession) != null) {
            return this.calcDiscount(cartEntry, discountType, discountValue);
        }
        return null;
    }

    @Override
    public PriceInfo applyOrderPromotion(CommerceSession commerceSession, Promotion promotion) throws CommerceException {
        return null;
    }

    @Override
    public PriceInfo applyShippingPromotion(CommerceSession commerceSession, Promotion promotion) throws CommerceException {
        return null;
    }

    @Deprecated
    @Override
    public synchronized String getMessage(SlingHttpServletRequest request, CommerceSession commerceSession, Promotion promotion) throws CommerceException {
        return this.getDescription(request, commerceSession, promotion);
    }

    @Override
    public synchronized String getDescription(SlingHttpServletRequest request, CommerceSession commerceSession, Promotion promotion) throws CommerceException {
        String promoPath = promotion.getPath();
        this.validateCache(promoPath);
        PairingsCache pairingCache = this.promoCache.get(promoPath);
        ArrayList<String> resolved = new ArrayList<String>();
        HashMap<String, String> potentials = new HashMap<String, String>();
        pairingCache.characterizeCart(commerceSession, resolved, potentials);
        PageManager pageManager = (PageManager)request.getResourceResolver().adaptTo(PageManager.class);
        I18n i18n = new I18n((HttpServletRequest)request);
        String description = "";
        for (String pathSet : resolved) {
            if (description.length() > 0) {
                description = description + "<br>";
            }
            try {
                String[] paths = pathSet.split(";");
                Product product1 = CommerceHelper.findCurrentProduct(pageManager.getPage(paths[0]));
                Product product2 = CommerceHelper.findCurrentProduct(pageManager.getPage(paths[1]));
                description = description + product1.getTitle() + " + " + product2.getTitle();
            }
            catch (Exception e) {
                description = description + i18n.get("error fetching products");
            }
        }
        for (Map.Entry potential : potentials.entrySet()) {
            String path1 = (String)potential.getKey();
            String path2 = (String)potential.getValue();
            if (description.length() > 0) {
                description = description + "<br>";
            }
            try {
                Product product1 = CommerceHelper.findCurrentProduct(pageManager.getPage(path1));
                Product product2 = CommerceHelper.findCurrentProduct(pageManager.getPage(path2));
                description = description + i18n.get("{0} <span class='cq-cc-cart-potential-match'> (suggest {1})</span>", null, new Object[]{product1.getTitle(), product2.getTitle()});
            }
            catch (Exception e) {
                description = description + i18n.get("error fetching products");
            }
        }
        if (description.length() == 0) {
            description = i18n.get("no pairings in cart");
        }
        return description;
    }

    @Override
    public synchronized Map<Integer, String> getMessages(SlingHttpServletRequest request, CommerceSession commerceSession, Promotion promotion) throws CommerceException {
        HashMap<Integer, String> messages = new HashMap<Integer, String>();
        ValueMap config = promotion.getConfig();
        String discountType = (String)config.get("discountType", (Object)"");
        BigDecimal discountValue = (BigDecimal)config.get("discountValue", (Object)BigDecimal.ZERO);
        String messageTemplate = (String)config.get("message", String.class);
        if (messageTemplate == null) {
            return messages;
        }
        String promoPath = promotion.getPath();
        this.validateCache(promoPath);
        PairingsCache pairingCache = this.promoCache.get(promoPath);
        I18n i18n = new I18n((HttpServletRequest)request);
        PageManager pageManager = (PageManager)request.getResourceResolver().adaptTo(PageManager.class);
        for (CommerceSession.CartEntry entry : commerceSession.getCartEntries()) {
            String companionTitle;
            Product product = entry.getProduct();
            String companionPath = pairingCache.getCompanion(product, commerceSession);
            if (companionPath == null) continue;
            try {
                Product companion = CommerceHelper.findCurrentProduct(pageManager.getPage(companionPath));
                companionTitle = companion.getTitle();
            }
            catch (Exception e) {
                companionTitle = i18n.get("unknown product");
            }
            PriceInfo discount = this.calcDiscount(entry, discountType, discountValue);
            messages.put(entry.getEntryIndex(), MessageFormat.format(messageTemplate, "", companionTitle, discount.getFormattedString()));
        }
        return messages;
    }

    public synchronized void getPotentials(CommerceSession commerceSession, Promotion promotion, Map<String, String> potentials) throws CommerceException {
        String promoPath = promotion.getPath();
        this.validateCache(promoPath);
        PairingsCache pairingCache = this.promoCache.get(promoPath);
        ArrayList<String> resolved = new ArrayList<String>();
        pairingCache.characterizeCart(commerceSession, resolved, potentials);
    }

    @Override
    public synchronized void invalidateCaches() {
        this.promoCache.clear();
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private synchronized void validateCache(String promoPath) {
        if (!this.promoCache.containsKey(promoPath)) {
            ResourceResolver serviceResolver = null;
            try {
                PairingsCache pairingsCache = new PairingsCache();
                this.promoCache.put(promoPath, pairingsCache);
                HashMap<String, String> authenticationInfo = new HashMap<String, String>();
                authenticationInfo.put("sling.service.subservice", "frontend");
                serviceResolver = this.resolverFactory.getServiceResourceResolver(authenticationInfo);
                Resource promoResource = serviceResolver.getResource(promoPath);
                Resource pairings = promoResource.getChild("jcr:content").getChild("config").getChild("pairings");
                Iterator iterator = pairings.listChildren();
                while (iterator.hasNext()) {
                    ValueMap pair = ResourceUtil.getValueMap((Resource)((Resource)iterator.next()));
                    pairingsCache.addPairing((String)pair.get("firstProductPath", String.class), (String)pair.get("secondProductPath", String.class));
                }
            }
            catch (Exception e) {
                this.log.error("Couldn't construct promotion cache for: " + promoPath, (Throwable)e);
            }
            finally {
                if (serviceResolver != null && serviceResolver.isLive()) {
                    serviceResolver.close();
                }
            }
        }
    }

    private class PairingsCache {
        private Map<String, List<String>> firstProductMap;
        private Map<String, List<String>> secondProductMap;

        private PairingsCache() {
            this.firstProductMap = new HashMap<String, List<String>>();
            this.secondProductMap = new HashMap<String, List<String>>();
        }

        public void addPairing(String firstProductPath, String secondProductPath) {
            if (firstProductPath == null || secondProductPath == null) {
                return;
            }
            if (this.firstProductMap.containsKey(firstProductPath)) {
                this.firstProductMap.get(firstProductPath).add(secondProductPath);
            } else {
                ArrayList<String> secondProductList = new ArrayList<String>();
                secondProductList.add(secondProductPath);
                this.firstProductMap.put(firstProductPath, secondProductList);
            }
            if (this.secondProductMap.containsKey(secondProductPath)) {
                this.secondProductMap.get(secondProductPath).add(firstProductPath);
            } else {
                ArrayList<String> firstProductList = new ArrayList<String>();
                firstProductList.add(firstProductPath);
                this.secondProductMap.put(secondProductPath, firstProductList);
            }
        }

        public String getCompanion(Product product, CommerceSession commerceSession) throws CommerceException {
            String secondProductPath = this.getProductPagePath(product);
            if (this.secondProductMap.containsKey(secondProductPath)) {
                List<String> firstProductList = this.secondProductMap.get(secondProductPath);
                for (String firstProductPath : firstProductList) {
                    if (!this.productInCart(firstProductPath, commerceSession)) continue;
                    return firstProductPath;
                }
            }
            return null;
        }

        public void characterizeCart(CommerceSession commerceSession, List<String> resolved, Map<String, String> potentials) throws CommerceException {
            for (CommerceSession.CartEntry entry : commerceSession.getCartEntries()) {
                String firstProductPath = this.getProductPagePath(entry.getProduct());
                if (!this.firstProductMap.containsKey(firstProductPath)) continue;
                List<String> secondProductsList = this.firstProductMap.get(firstProductPath);
                boolean match = false;
                for (String secondProductPath : secondProductsList) {
                    if (!this.productInCart(secondProductPath, commerceSession)) continue;
                    resolved.add(firstProductPath + ";" + secondProductPath);
                    match = true;
                }
                if (match) continue;
                potentials.put(firstProductPath, secondProductsList.get(0));
            }
        }

        private String getProductPagePath(Product product) {
            String href = product.getPagePath();
            int extension = href.indexOf(".html");
            if (extension > 0) {
                return href.substring(0, extension);
            }
            int fragment = href.indexOf(35);
            if (fragment > 0) {
                return href.substring(0, fragment);
            }
            return href;
        }

        private boolean productInCart(String productPath, CommerceSession commerceSession) throws CommerceException {
            for (CommerceSession.CartEntry entry : commerceSession.getCartEntries()) {
                if (!this.getProductPagePath(entry.getProduct()).equals(productPath)) continue;
                return true;
            }
            return false;
        }
    }

}