ClientContextCartServlet.java 15 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.TidyJSONWriter
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.api.PageManager
 *  javax.servlet.ServletException
 *  org.apache.commons.collections.Predicate
 *  org.apache.commons.lang.StringUtils
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.api.servlets.SlingAllMethodsServlet
 *  org.apache.sling.commons.json.JSONArray
 *  org.apache.sling.commons.json.JSONException
 *  org.apache.sling.commons.json.JSONObject
 *  org.apache.sling.commons.json.io.JSONWriter
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.commerce.impl;

import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.CommerceService;
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.PromotionInfo;
import com.adobe.cq.commerce.api.promotion.PromotionManager;
import com.adobe.cq.commerce.api.promotion.VoucherInfo;
import com.adobe.cq.commerce.common.DefaultJcrCartEntry;
import com.day.cq.commons.TidyJSONWriter;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.json.io.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service
@Properties(value={@Property(name="service.description", value={"Provides commerce services for the ClientContext"}), @Property(name="sling.servlet.resourceTypes", value={"sling/servlet/default"}), @Property(name="sling.servlet.selectors", value={"commerce.cart"}), @Property(name="sling.servlet.extensions", value={"json"}), @Property(name="sling.servlet.methods", value={"POST"})})
public class ClientContextCartServlet
extends SlingAllMethodsServlet {
    public static final String TIDY = "tidy";
    private static final Logger log = LoggerFactory.getLogger(ClientContextCartServlet.class);

    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        JSONObject clientContextCart;
        try {
            clientContextCart = new JSONObject(request.getParameter("cart"));
        }
        catch (JSONException e) {
            response.sendError(400, "Cart data not valid: " + e.getMessage());
            return;
        }
        try {
            String language;
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            TidyJSONWriter writer = new TidyJSONWriter((Writer)response.getWriter());
            writer.setTidy("true".equals(request.getParameter("tidy")));
            Resource resource = request.getResource();
            ResourceResolver resolver = resource.getResourceResolver();
            CommerceService commerceService = (CommerceService)resource.adaptTo(CommerceService.class);
            CommerceSession commerceSession = commerceService != null ? commerceService.login(request, response) : null;
            PageManager pageManager = (PageManager)resolver.adaptTo(PageManager.class);
            Page page = pageManager != null ? pageManager.getContainingPage(resource) : null;
            String string = language = page != null ? page.getLanguage(false).getLanguage() : null;
            if (commerceSession != null) {
                if (!clientContextCart.optBoolean("ignorePost", false)) {
                    this.updateEntries(clientContextCart, commerceService, commerceSession);
                    this.updateVouchers(clientContextCart, commerceSession);
                    this.updatePromotions(clientContextCart, commerceSession);
                }
                this.writeCart((JSONWriter)writer, commerceSession, language, resolver, request);
            } else {
                writer.object().endObject();
            }
        }
        catch (Exception e) {
            response.sendError(500, "Cart update failed: " + e.getMessage());
            log.warn("Could not update cart via ClientContext", (Throwable)e);
        }
    }

    private void updateEntries(JSONObject ccCart, CommerceService commerceService, CommerceSession commerceSession) throws CommerceException, JSONException {
        ArrayList<CommerceSession.CartEntry> entries = new ArrayList<CommerceSession.CartEntry>(commerceSession.getCartEntries());
        HashMap<String, CommerceSession.CartEntry> entryMap = new HashMap<String, CommerceSession.CartEntry>();
        for (CommerceSession.CartEntry entry : entries) {
            entryMap.put(entry.getProduct().getPath(), entry);
        }
        JSONArray ccEntries = ccCart.optJSONArray("entries");
        for (int i = 0; ccEntries != null && i < ccEntries.length(); ++i) {
            JSONObject ccEntry = ccEntries.getJSONObject(i);
            Product product = commerceService.getProduct(ccEntry.getString("path"));
            int quantity = Integer.parseInt(ccEntry.getString("quantity"));
            if (product == null || quantity <= 0) continue;
            CommerceSession.CartEntry entry2 = (CommerceSession.CartEntry)entryMap.get(product.getPath());
            if (entry2 == null) {
                commerceSession.addCartEntry(product, quantity);
                continue;
            }
            if (entry2.getQuantity() != quantity) {
                commerceSession.modifyCartEntry(entry2.getEntryIndex(), quantity);
            }
            entryMap.remove(product.getPath());
        }
        CommerceSession.CartEntry[] values = entryMap.values().toArray(new CommerceSession.CartEntry[entryMap.size()]);
        Arrays.sort(values, new Comparator<CommerceSession.CartEntry>(){

            @Override
            public int compare(CommerceSession.CartEntry o1, CommerceSession.CartEntry o2) {
                return - o1.getQuantity() - o2.getQuantity();
            }
        });
        for (CommerceSession.CartEntry entry2 : values) {
            commerceSession.deleteCartEntry(entry2.getEntryIndex());
        }
    }

    private void updateVouchers(JSONObject ccCart, CommerceSession commerceSession) throws CommerceException, JSONException {
        HashSet<String> sessionVouchers = new HashSet<String>();
        for (VoucherInfo voucher : commerceSession.getVoucherInfos()) {
            sessionVouchers.add(voucher.getCode());
        }
        HashSet<String> contextVouchers = new HashSet<String>();
        JSONArray ccVouchers = ccCart.optJSONArray("vouchers");
        for (int i = 0; ccVouchers != null && i < ccVouchers.length(); ++i) {
            contextVouchers.add(ccVouchers.getJSONObject(i).getString("code"));
        }
        for (String code2 : contextVouchers) {
            if (!sessionVouchers.contains(code2)) {
                try {
                    commerceSession.addVoucher(code2);
                }
                catch (CommerceException e) {
                    // empty catch block
                }
            }
            sessionVouchers.remove(code2);
        }
        for (String code2 : sessionVouchers) {
            commerceSession.removeVoucher(code2);
        }
    }

    private void updatePromotions(JSONObject ccCart, CommerceSession commerceSession) throws CommerceException, JSONException {
        HashSet<String> sessionPromotions = new HashSet<String>();
        for (PromotionInfo promo : commerceSession.getPromotions()) {
            sessionPromotions.add(promo.getPath());
        }
        JSONArray ccPromotions = ccCart.optJSONArray("promotions");
        HashSet<String> contextPromotions = new HashSet<String>();
        for (int i = 0; ccPromotions != null && i < ccPromotions.length(); ++i) {
            contextPromotions.add(ccPromotions.getJSONObject(i).getString("path"));
        }
        for (String path2 : contextPromotions) {
            if (!sessionPromotions.contains(path2)) {
                try {
                    commerceSession.addPromotion(path2);
                }
                catch (CommerceException e) {
                    // empty catch block
                }
            }
            sessionPromotions.remove(path2);
        }
        for (String path2 : sessionPromotions) {
            commerceSession.removePromotion(path2);
        }
    }

    private void writeCart(JSONWriter writer, CommerceSession commerceSession, String language, ResourceResolver resolver, SlingHttpServletRequest request) throws CommerceException, JSONException {
        PromotionManager pm = resolver != null ? (PromotionManager)resolver.adaptTo(PromotionManager.class) : null;
        String contextPath = request.getContextPath();
        Map serverPromotionsMap = new HashMap<String, String>();
        if (pm != null) {
            for (Promotion promotion : pm.getAvailablePromotions(resolver)) {
                ValueMap props;
                String code;
                if (!"/libs/commerce/components/promotion/server".equals(promotion.getType()) || !StringUtils.isNotBlank((String)(code = (String)(props = promotion.getConfig()).get("code", (Object)""))) || ((Boolean)props.get("disabled", (Object)Boolean.FALSE)).booleanValue()) continue;
                serverPromotionsMap.put(code, StringUtils.join(promotion.getSegments(), (String)","));
            }
        }
        Map clientPromotionsMap = new HashMap();
        if (pm != null && request != null) {
            clientPromotionsMap = pm.getPromotionsMap(request);
        }
        writer.object();
        writer.key("entries").array();
        for (CommerceSession.CartEntry e : commerceSession.getCartEntries()) {
            DefaultJcrCartEntry entry;
            ValueMap properties;
            writer.object();
            writer.key("title").value((Object)e.getProduct().getTitle(language));
            writer.key("quantity").value((long)e.getQuantity());
            List<PriceInfo> priceInfos = e.getPriceInfo(null);
            if (priceInfos != null && priceInfos.size() > 0) {
                writer.key("priceFormatted").value((Object)priceInfos.get(0).getFormattedString());
                writer.key("price").value((Object)priceInfos.get(0).getAmount());
            } else {
                log.error("Empty PriceInfo list for product!", (Object)e.getProduct().getPath());
                writer.key("priceFormatted").value((Object)"$0.00");
                writer.key("price").value(0);
            }
            String thumbnail = e.getProduct().getThumbnailUrl(".64.transparent");
            if (StringUtils.isNotEmpty((String)thumbnail)) {
                writer.key("thumbnail").value((Object)(contextPath + thumbnail));
            }
            writer.key("page").value((Object)e.getProduct().getPagePath());
            writer.key("path").value((Object)e.getProduct().getPath());
            if (e instanceof DefaultJcrCartEntry && !(properties = (entry = (DefaultJcrCartEntry)e).getProperties()).isEmpty()) {
                writer.key("properties").object();
                for (String key : properties.keySet()) {
                    writer.key(key).value(properties.get(key, String.class));
                }
                writer.endObject();
            }
            writer.endObject();
        }
        writer.endArray();
        boolean serverSideResolution = !commerceSession.supportsClientsidePromotionResolution();
        writer.key("promotions").array();
        for (PromotionInfo p : commerceSession.getPromotions()) {
            if (p.getStatus() != PromotionInfo.PromotionStatus.FIRED && p.getStatus() != PromotionInfo.PromotionStatus.POTENTIAL) continue;
            writer.object();
            writer.key("title").value((Object)p.getTitle());
            writer.key("description").value((Object)p.getDescription());
            writer.key("message").value((Object)p.getMessage());
            writer.key("path").value((Object)p.getPath());
            writer.key("status").value((Object)p.getStatus().toString());
            writer.key("cartEntryIndex").value((Object)p.getCartEntryIndex());
            if (serverSideResolution) {
                writer.key("resolve").value((Object)"true");
            }
            writer.endObject();
        }
        writer.endArray();
        writer.key("vouchers").array();
        for (VoucherInfo c : commerceSession.getVoucherInfos()) {
            writer.object();
            writer.key("code").value((Object)c.getCode());
            writer.key("title").value((Object)c.getTitle());
            writer.key("description").value((Object)c.getDescription());
            writer.key("message").value((Object)c.getMessage());
            writer.key("path").value((Object)c.getPath());
            writer.endObject();
        }
        writer.endArray();
        List<PriceInfo> priceInfos = commerceSession.getCartPriceInfo(null);
        if (priceInfos != null && priceInfos.size() > 0) {
            writer.key("totalPrice").value((Object)priceInfos.get(0).getFormattedString());
            writer.key("totalPriceFloat").value((Object)priceInfos.get(0).getAmount());
        } else {
            log.error("Empty PriceInfo list for cart!");
            writer.key("totalPrice").value((Object)"$0.00");
            writer.key("totalPriceFloat").value(0);
        }
        writer.key("promotionsMap").array();
        Map map = commerceSession.supportsClientsidePromotionResolution() ? clientPromotionsMap : serverPromotionsMap;
        for (Map.Entry entry : map.entrySet()) {
            writer.object();
            writer.key("segments").value(entry.getValue());
            writer.key("path").value(entry.getKey());
            writer.endObject();
        }
        writer.endArray();
        writer.endObject();
    }

}