ProductViewHandler.java 13.2 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.cq.commerce.api.Product
 *  com.adobe.granite.xss.XSSAPI
 *  com.day.cq.search.Predicate
 *  com.day.cq.search.PredicateConverter
 *  com.day.cq.search.PredicateGroup
 *  com.day.cq.search.Query
 *  com.day.cq.search.QueryBuilder
 *  com.day.cq.search.result.Hit
 *  com.day.cq.search.result.SearchResult
 *  com.day.cq.tagging.Tag
 *  com.day.cq.tagging.TagManager
 *  com.day.cq.wcm.core.contentfinder.Hit
 *  com.day.cq.wcm.core.contentfinder.ViewHandler
 *  com.day.cq.wcm.core.contentfinder.ViewQuery
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.query.Row
 *  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.ReferencePolicy
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.jackrabbit.commons.query.GQL
 *  org.apache.jackrabbit.commons.query.GQL$Filter
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ValueMap
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.commerce.pim.impl.contentfinder;

import com.adobe.cq.commerce.api.Product;
import com.adobe.granite.xss.XSSAPI;
import com.day.cq.search.Predicate;
import com.day.cq.search.PredicateConverter;
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.SearchResult;
import com.day.cq.tagging.Tag;
import com.day.cq.tagging.TagManager;
import com.day.cq.wcm.core.contentfinder.Hit;
import com.day.cq.wcm.core.contentfinder.ViewHandler;
import com.day.cq.wcm.core.contentfinder.ViewQuery;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Row;
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.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.commons.query.GQL;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service
@Properties(value={@Property(name="service.description", value={"Handles the display of the products tab in the content finder"}), @Property(name="sling.servlet.paths", value={"/bin/wcm/contentfinder/product/view"})})
public class ProductViewHandler
extends ViewHandler {
    private static Logger log = LoggerFactory.getLogger(ProductViewHandler.class);
    private TagManager tagManager;
    @Reference
    private XSSAPI xssAPI;
    @Reference(policy=ReferencePolicy.STATIC)
    private QueryBuilder queryBuilder;
    private static final String DEFAULT_START_PATH = "/etc/commerce/products";
    public static final String PROPPERTY_STEP = "*/";
    private static final String COMMERCE_TYPE = "cq:commerceType";
    private static final String PRODUCT_COMMERCE_TYPE = "product";
    private static final String TAGS_PROP = "tags";
    private static final String CQ_TAGS_PROP = "cq:tags";
    private Set<String> predicateSet;

    protected ViewQuery createQuery(SlingHttpServletRequest request, Session session, String queryString) throws RepositoryException {
        String startPath;
        if (queryString != null) {
            queryString = ProductViewHandler.preserveWildcards(queryString);
        }
        PredicateGroup gqlPredicateGroup = PredicateConverter.createPredicatesFromGQL((String)queryString);
        this.tagManager = (TagManager)request.getResourceResolver().adaptTo(TagManager.class);
        this.predicateSet = this.customizePredicateGroup(gqlPredicateGroup);
        RequestPathInfo pathInfo = request.getRequestPathInfo();
        String string = startPath = pathInfo.getSuffix() != null && pathInfo.getSuffix().startsWith("/etc/commerce/products") ? pathInfo.getSuffix() : "/etc/commerce/products";
        if (!this.predicateSet.contains("path")) {
            gqlPredicateGroup.add(new Predicate("path").set("path", startPath));
        }
        if (gqlPredicateGroup.get("limit") == null) {
            String limit = request.getParameter("limit");
            if (limit != null && !limit.equals("")) {
                int offset = Integer.parseInt(StringUtils.substringBefore((String)limit, (String)".."));
                int total = Integer.parseInt(StringUtils.substringAfter((String)limit, (String)".."));
                gqlPredicateGroup.set("limit", Long.toString(total - offset));
                gqlPredicateGroup.set("offset", Long.toString(offset));
            } else {
                gqlPredicateGroup.set("limit", Long.toString(20));
            }
        }
        ProductViewHandler.addProductConstraint(request, gqlPredicateGroup);
        if (!this.predicateSet.contains("orderby")) {
            gqlPredicateGroup.add(new Predicate("orderby").set("orderby", "@jcr:lastModified").set("sort", "desc"));
        }
        return new GQLViewQuery(request.getResourceResolver(), this.xssAPI, this.queryBuilder, gqlPredicateGroup, this.predicateSet);
    }

    private static Hit createHit(Product product, String excerpt, XSSAPI xssAPI) throws RepositoryException {
        Hit hit = new Hit();
        String path = product.getPath();
        String name = path.substring(path.lastIndexOf("/") + 1);
        String title = product.getTitle();
        if (title == null || title.length() == 0) {
            title = name;
        }
        hit.set("name", (Object)xssAPI.encodeForHTML(name));
        hit.set("path", (Object)path);
        hit.set("thumbnail", (Object)xssAPI.getValidHref(product.getThumbnailUrl(48)));
        hit.set("title", (Object)xssAPI.encodeForHTML(title));
        hit.set("sku", (Object)xssAPI.encodeForHTML(product.getSKU()));
        hit.set("excerpt", (Object)xssAPI.filterHTML(excerpt));
        return hit;
    }

    private Set<String> customizePredicateGroup(PredicateGroup predicateGroup) {
        if (predicateGroup == null) {
            return new HashSet<String>();
        }
        HashSet<String> predicateSet = new HashSet<String>();
        for (int i = 0; i < predicateGroup.size(); ++i) {
            if (predicateGroup.get(i) instanceof PredicateGroup) {
                PredicateGroup optionalGrp = (PredicateGroup)predicateGroup.get(i);
                predicateSet.addAll(this.customizePredicateGroup(optionalGrp));
                predicateGroup.set(i, (Predicate)optionalGrp);
                continue;
            }
            if (!(predicateGroup.get(i) instanceof Predicate)) continue;
            Predicate predicate = predicateGroup.get(i);
            predicateSet.add(predicate.getType());
            this.modifyPredicate(predicateGroup, predicate, i);
        }
        return predicateSet;
    }

    private void modifyPredicate(PredicateGroup parentGroup, Predicate predicate, int index) {
        String fulltext;
        String property = predicate.get("property");
        if ("property".equals(predicate.getType())) {
            String value = predicate.get("value");
            if (property.equals("tags") || property.equals("tag")) {
                Tag tag;
                predicate.set("property", "cq:tags");
                parentGroup.set(index, predicate);
                if (this.tagManager != null && (tag = this.tagManager.resolve(value)) == null) {
                    Predicate tagSearchPredicate = new Predicate("tagsearch");
                    tagSearchPredicate.set("property", "cq:tags");
                    tagSearchPredicate.set("tagsearch", value);
                    parentGroup.set(index, tagSearchPredicate);
                }
            } else {
                int depth = StringUtils.countMatches((String)(property = ProductViewHandler.revertWildcards(property)), (String)"*/");
                if (depth > 0) {
                    predicate.set("property", property.replace("*/", ""));
                    predicate.set("depth", String.valueOf(depth));
                    parentGroup.set(index, predicate);
                }
            }
        } else if ("fulltext".equals(predicate.getType()) && (fulltext = predicate.get("fulltext", "")) != null) {
            if (fulltext != null) {
                fulltext = ProductViewHandler.revertWildcards(fulltext);
            }
            predicate.set("fulltext", fulltext);
            Predicate tagSearchPredicate = new Predicate("tagsearch");
            tagSearchPredicate.set("property", "cq:tags");
            tagSearchPredicate.set("tagsearch", fulltext);
            PredicateGroup optionalGrp = new PredicateGroup();
            optionalGrp.setAllRequired(false);
            optionalGrp.add(predicate);
            optionalGrp.add(tagSearchPredicate);
            parentGroup.set(index, (Predicate)optionalGrp);
        }
    }

    private static String preserveWildcards(String queryString) {
        if (queryString != null) {
            queryString = queryString.replace("*", "%");
        }
        return queryString;
    }

    private static String revertWildcards(String queryString) {
        if (queryString != null) {
            queryString = queryString.replace("%", "*");
        }
        return queryString;
    }

    private static void addProductConstraint(SlingHttpServletRequest request, PredicateGroup gqlPredicateGroup) {
        Predicate predicate = new Predicate("property");
        predicate.set("property", "cq:commerceType");
        predicate.set("value", "product");
        predicate.set("operation", "equals");
        gqlPredicateGroup.add(predicate);
    }

    protected void bindXssAPI(XSSAPI xSSAPI) {
        this.xssAPI = xSSAPI;
    }

    protected void unbindXssAPI(XSSAPI xSSAPI) {
        if (this.xssAPI == xSSAPI) {
            this.xssAPI = null;
        }
    }

    protected void bindQueryBuilder(QueryBuilder queryBuilder) {
        this.queryBuilder = queryBuilder;
    }

    protected void unbindQueryBuilder(QueryBuilder queryBuilder) {
        if (this.queryBuilder == queryBuilder) {
            this.queryBuilder = null;
        }
    }

    private static class GQLViewQuery
    implements ViewQuery {
        Session session;
        ResourceResolver resolver;
        private final XSSAPI xssAPI;
        private final QueryBuilder qb;
        private final PredicateGroup predicateGroup;
        private final Set<String> predicateSet;

        public GQLViewQuery(ResourceResolver resolver, XSSAPI xssAPI, QueryBuilder qb, PredicateGroup predicateGroup, Set<String> predicateSet) {
            this.session = (Session)resolver.adaptTo(Session.class);
            this.resolver = resolver;
            this.xssAPI = xssAPI;
            this.predicateGroup = predicateGroup;
            this.qb = qb;
            this.predicateSet = predicateSet;
        }

        public Collection<Hit> execute() {
            ArrayList<Hit> hits = new ArrayList<Hit>();
            Query query = this.qb.createQuery(this.predicateGroup, this.session);
            Iterator searchHits = query.getResult().getHits().iterator();
            try {
                while (searchHits.hasNext()) {
                    String excerpt;
                    com.day.cq.search.result.Hit searchHit = (com.day.cq.search.result.Hit)searchHits.next();
                    String path = searchHit.getPath();
                    Product product = (Product)this.resolver.getResource(path).adaptTo(Product.class);
                    if (product == null) continue;
                    try {
                        excerpt = searchHit.getExcerpt();
                    }
                    catch (Exception e) {
                        excerpt = "";
                    }
                    hits.add(ProductViewHandler.createHit(product, excerpt, this.xssAPI));
                }
            }
            catch (RepositoryException re) {
                log.error("A repository error occurred", (Throwable)re);
            }
            return hits;
        }
    }

    private static class ProductFilter
    implements GQL.Filter {
        ResourceResolver resolver;

        ProductFilter(ResourceResolver resolver) {
            this.resolver = resolver;
        }

        public boolean include(Row row) throws RepositoryException {
            String path = row.getPath();
            Resource resource = this.resolver.getResource(path);
            if (resource == null) {
                return false;
            }
            ValueMap valueMap = (ValueMap)resource.adaptTo(ValueMap.class);
            return valueMap.containsKey((Object)"cq:commerceType") && valueMap.get((Object)"cq:commerceType").equals("product");
        }
    }

}