ProductDataServlet.java 14.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.cq.commerce.api.CommerceException
 *  com.adobe.cq.commerce.api.CommerceService
 *  com.adobe.cq.commerce.api.Product
 *  com.day.cq.commons.jcr.JcrUtil
 *  com.day.cq.commons.servlets.HtmlStatusResponseHelper
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.api.PageManager
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.servlet.ServletException
 *  javax.servlet.http.HttpServletResponse
 *  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.Reference
 *  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.ResourceUtil
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.api.servlets.HtmlResponse
 *  org.apache.sling.api.servlets.SlingAllMethodsServlet
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.commerce.pim.impl;

import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.CommerceService;
import com.adobe.cq.commerce.api.Product;
import com.adobe.cq.commerce.pim.api.CatalogBlueprintImporter;
import com.adobe.cq.commerce.pim.api.ProductImporter;
import com.adobe.cq.commerce.pim.api.ProductServicesManager;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.commons.servlets.HtmlStatusResponseHelper;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
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.Reference;
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.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.HtmlResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service
@Properties(value={@Property(name="service.description", value={"Provides product information management services, such as product import"}), @Property(name="sling.servlet.paths", value={"/libs/commerce/products"}), @Property(name="sling.servlet.methods", value={"GET", "POST"})})
public class ProductDataServlet
extends SlingAllMethodsServlet {
    private static final Logger log = LoggerFactory.getLogger(ProductDataServlet.class);
    private static final long serialVersionUID = 1198256761592900348L;
    private static String NN_PRODUCT_IMAGE = "image";
    private static String NN_PRODUCT_ASSETS = "assets";
    @Reference
    private ProductServicesManager productServicesManager;

    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        String operation = request.getParameter(":operation");
        String provider = request.getParameter("provider");
        if (StringUtils.isEmpty((String)operation)) {
            response.sendError(400, "No :operation (import|importCatalogBlueprint|export) specified.");
            return;
        }
        if (operation.equalsIgnoreCase("import")) {
            String fallbackProvider;
            ProductImporter importer;
            Map<String, ProductImporter> productImporters = this.productServicesManager.getProductImporters();
            if (StringUtils.isEmpty((String)provider) && !productImporters.isEmpty()) {
                provider = productImporters.keySet().iterator().next();
            }
            if ((importer = productImporters.get(provider)) == null && !StringUtils.isEmpty((String)(fallbackProvider = request.getParameter("fallbackProvider"))) && productImporters.containsKey(fallbackProvider)) {
                importer = productImporters.get(fallbackProvider);
            }
            if (importer == null) {
                response.sendError(400, "No ProductImporter service registered for " + provider);
            } else {
                importer.importProducts(request, response);
            }
        } else if (operation.equalsIgnoreCase("importCatalogBlueprint")) {
            CatalogBlueprintImporter blueprintImporter;
            Map<String, CatalogBlueprintImporter> blueprintImporters = this.productServicesManager.getBlueprintImporters();
            if (StringUtils.isEmpty((String)provider) && !blueprintImporters.isEmpty()) {
                provider = blueprintImporters.keySet().iterator().next();
            }
            if ((blueprintImporter = blueprintImporters.get(provider)) == null) {
                response.sendError(400, "No CatalogBlueprintImporter service registered for " + provider);
            } else {
                blueprintImporter.importBlueprints(request, response);
            }
        } else if (operation.equalsIgnoreCase("export")) {
            this.exportCsv(request, response);
        } else if (operation.equalsIgnoreCase("buildVariantHierarchy")) {
            this.updateVariantHierarchy(request, response, true);
        } else if (operation.equalsIgnoreCase("checkVariantHierarchy")) {
            this.updateVariantHierarchy(request, response, false);
        } else {
            response.sendError(400, "Unknown :operation (" + operation + ").");
        }
    }

    protected void updateVariantHierarchy(SlingHttpServletRequest request, SlingHttpServletResponse response, boolean force) throws ServletException, IOException {
        Resource productReference;
        Page page;
        Product pimData;
        String productDataPath;
        ResourceResolver resourceResolver = request.getResourceResolver();
        String productReferencePath = request.getParameter("catalogPath");
        try {
            productReference = resourceResolver.getResource(productReferencePath);
        }
        catch (Exception e) {
            response.sendError(500, "Product [" + productReferencePath + "] not found.");
            return;
        }
        PageManager pageManager = (PageManager)resourceResolver.adaptTo(PageManager.class);
        Page page2 = page = pageManager != null ? pageManager.getContainingPage(productReferencePath) : null;
        if (page == null) {
            response.sendError(500, "Product reference not on a page.");
        }
        if (StringUtils.isEmpty((String)(productDataPath = request.getParameter("productDataPath")))) {
            productDataPath = (String)ResourceUtil.getValueMap((Resource)productReference).get("productData", String.class);
        }
        if (StringUtils.isEmpty((String)productDataPath)) {
            response.sendError(500, "No product data reference exists or was supplied.");
        }
        try {
            pimData = (Product)resourceResolver.getResource(productDataPath).adaptTo(Product.class);
        }
        catch (Exception e) {
            response.sendError(500, "Product data [" + productDataPath + "] not found.");
            return;
        }
        ArrayList<String> messageLog = new ArrayList<String>();
        try {
            int variationCount = this.updateProduct(productReference, pimData, page, force, messageLog);
            String summary = "" + variationCount + " variations created.";
            this.respondWithLog(response, summary, messageLog);
        }
        catch (Exception e) {
            log.error("Error encountered updating product", (Throwable)e);
            response.sendError(500, "Errors encountered updating product.");
        }
    }

    protected int updateProduct(Resource productReference, Product pimData, Page page, boolean force, List<String> messageLog) throws CommerceException, RepositoryException {
        Node productReferenceNode = (Node)productReference.adaptTo(Node.class);
        String existingMaster = (String)page.getProperties().get("cq:productMaster", String.class);
        if (!force && existingMaster != null && existingMaster.equals(pimData.getPath())) {
            return 0;
        }
        Node pageProperties = (Node)page.getContentResource().adaptTo(Node.class);
        pageProperties.setProperty("cq:productMaster", pimData.getPath());
        productReferenceNode.setProperty("productData", pimData.getPath());
        NodeIterator it = productReferenceNode.getNodes();
        while (it.hasNext()) {
            it.nextNode().remove();
        }
        this.addAssets(productReferenceNode, pimData, messageLog);
        int count = this.addVariations(productReferenceNode, pimData, messageLog);
        try {
            CommerceService commerceService = (CommerceService)pimData.adaptTo(CommerceService.class);
            commerceService.productRolloutHook(pimData, page, (Product)productReference.adaptTo(Product.class));
        }
        catch (Exception e) {
            messageLog.add("ProductRolloutHook failed for " + productReference.getPath() + ".");
        }
        productReferenceNode.getSession().save();
        return count;
    }

    protected int addVariations(Node productReference, Product pimData, List<String> messageLog) throws CommerceException {
        int count = 0;
        Iterator it = pimData.getVariants();
        while (it.hasNext()) {
            Product variant = (Product)it.next();
            String name = JcrUtil.createValidName((String)variant.getSKU().trim().replace(" ", "-"));
            try {
                Node variantRef = JcrUtil.createUniqueNode((Node)productReference, (String)name, (String)"nt:unstructured", (Session)productReference.getSession());
                variantRef.setProperty("cq:commerceType", "variant");
                variantRef.setProperty("sling:resourceType", productReference.getProperty("sling:resourceType").getString());
                variantRef.setProperty("productData", variant.getPath());
                messageLog.add("Created " + variantRef.getPath());
                ++count;
                this.addAssets(variantRef, variant, messageLog);
            }
            catch (Exception e) {
                messageLog.add("Error adding variation " + name + ".");
            }
        }
        return count;
    }

    @Deprecated
    public void addImage(Node productNode, Product pimData, List<String> messageLog) {
        this.addAssets(productNode, pimData, messageLog, NN_PRODUCT_IMAGE);
    }

    public void addAssets(Node productNode, Product pimData, List<String> messageLog) {
        this.addAssets(productNode, pimData, messageLog, NN_PRODUCT_IMAGE);
        this.addAssets(productNode, pimData, messageLog, NN_PRODUCT_ASSETS);
    }

    private void addAssets(Node productNode, Product pimData, List<String> messageLog, String assetContainer) {
        String path = "";
        try {
            path = productNode.getPath();
            Resource masterAssets = this.getProductAssets(pimData, assetContainer);
            if (masterAssets != null) {
                JcrUtil.copy((Node)((Node)masterAssets.adaptTo(Node.class)), (Node)productNode, (String)assetContainer);
            } else {
                Node imageNode = JcrUtil.createUniqueNode((Node)productNode, (String)assetContainer, (String)"nt:unstructured", (Session)productNode.getSession());
                imageNode.setProperty("sling:resourceType", productNode.getProperty("sling:resourceType").getString() + "/" + assetContainer);
            }
        }
        catch (Exception e) {
            messageLog.add("Failed to update image for " + path + ".");
        }
    }

    private Resource getProductAssets(Product product, String assetContainer) {
        if (product == null || assetContainer == null) {
            return null;
        }
        List assets = product.getAssets();
        if (assets != null) {
            for (Resource asset : assets) {
                if (NN_PRODUCT_IMAGE.equals(assetContainer) && NN_PRODUCT_IMAGE.equals(asset.getName())) {
                    return asset;
                }
                Resource assetParent = asset.getParent();
                if (!NN_PRODUCT_ASSETS.equals(assetContainer) || !NN_PRODUCT_ASSETS.equals(assetParent.getName())) continue;
                return assetParent;
            }
        }
        return null;
    }

    protected void respondWithLog(SlingHttpServletResponse response, String summary, List<String> messageLog) throws IOException {
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        PrintWriter pw = response.getWriter();
        pw.println("<html><body>");
        pw.println("<pre>");
        pw.println(summary);
        pw.println("");
        for (String msg : messageLog) {
            pw.println(msg);
        }
        pw.println("</pre>");
        pw.println("</body></html>");
        pw.flush();
    }

    protected void exportCsv(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        HtmlResponse resp = HtmlStatusResponseHelper.createStatusResponse((boolean)false, (String)"Export CSV not yet implemented.");
        resp.send((HttpServletResponse)response, true);
    }

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        HtmlResponse resp = HtmlStatusResponseHelper.createStatusResponse((boolean)false, (String)"GET not yet implemented.");
        resp.send((HttpServletResponse)response, true);
    }

    protected void bindProductServicesManager(ProductServicesManager productServicesManager) {
        this.productServicesManager = productServicesManager;
    }

    protected void unbindProductServicesManager(ProductServicesManager productServicesManager) {
        if (this.productServicesManager == productServicesManager) {
            this.productServicesManager = null;
        }
    }
}