AbstractCommerceSavedSearchHandler.java 12.8 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.omnisearch.api.core.OmniSearchException
 *  com.adobe.granite.omnisearch.spi.core.SavedSearchHandler
 *  com.day.cq.commons.jcr.JcrUtil
 *  com.day.cq.search.PredicateGroup
 *  com.day.cq.search.Query
 *  com.day.cq.search.QueryBuilder
 *  com.day.cq.search.result.SearchResult
 *  javax.jcr.Node
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  org.apache.commons.lang.StringUtils
 *  org.apache.jackrabbit.api.security.user.Authorizable
 *  org.apache.sling.api.resource.ModifiableValueMap
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.resource.collection.ResourceCollection
 *  org.apache.sling.resource.collection.ResourceCollectionManager
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.commerce.impl.omnisearch;

import com.adobe.granite.omnisearch.api.core.OmniSearchException;
import com.adobe.granite.omnisearch.spi.core.SavedSearchHandler;
import com.day.cq.commons.jcr.JcrUtil;
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 java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.resource.collection.ResourceCollection;
import org.apache.sling.resource.collection.ResourceCollectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractCommerceSavedSearchHandler
implements SavedSearchHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCommerceSavedSearchHandler.class);
    protected static final String REQUEST_PARAMETER_TITLE = "title";
    protected static final String REQUEST_PARAMETER_DESC = "description";
    protected static final String REQUEST_PARAM_AUTO_ADJUST_TITLE = "autoAdjustTitle";
    protected static final String REQUEST_PARAM_RESOURCE_PATH = "resourcePath";
    protected static final Set<String> defaultReqParams = new HashSet<String>();
    private static final String PREFERENCES_SAVED_SEARCH_PATH = "/preferences/omnisearch/commerce/";
    static final String CREATE_COMMAND = "create";
    static final String UPDATE_COMMAND = "update";
    private static final String PN_CQ_SAVEDQUERY = "savedquery";
    private static final String PARAM_SEP = "&";
    private static final String NAME_VALUE_SEPARATOR = "=";
    private static final String LOCATION_PARAM = "location";

    public boolean deleteSavedSearch(ResourceResolver resourceResolver, String path) {
        return false;
    }

    public Iterator<Resource> getSavedSearches(ResourceResolver resourceResolver, long limit, long offset) {
        try {
            String path = this.getSavedSearchPath(resourceResolver);
            HashMap<String, String> map = new HashMap<String, String>();
            map.put("path", path);
            map.put("type", "nt:unstructured");
            map.put("property", "sling:resourceType");
            map.put("property.value", "sling/collection");
            Session session = (Session)resourceResolver.adaptTo(Session.class);
            Query query = this.getQueryBuilder().createQuery(PredicateGroup.create(map), session);
            SearchResult result = query.getResult();
            return result.getResources();
        }
        catch (RepositoryException e) {
            LOGGER.error("Error retrieving saved searches for omnisearch location " + this.getID(), (Throwable)e);
            return Collections.emptyIterator();
        }
    }

    public Map<String, String> getSavedSearchParameters(ResourceResolver resourceResolver, String path) {
        Resource resource = null;
        if (!StringUtils.isEmpty((String)path)) {
            resource = resourceResolver.getResource(path);
        }
        if (resource == null) {
            return Collections.emptyMap();
        }
        ResourceCollection collection = (ResourceCollection)resource.adaptTo(ResourceCollection.class);
        if (collection == null) {
            return Collections.emptyMap();
        }
        Session session = (Session)resourceResolver.adaptTo(Session.class);
        String queryPath = resource.getPath() + "/" + "savedquery";
        try {
            Query storedQuery = this.getQueryBuilder().loadQuery(queryPath, session);
            String queryParams = storedQuery.getPredicates().toURL();
            return this.parse(queryParams);
        }
        catch (Exception e) {
            return Collections.emptyMap();
        }
    }

    public Resource createOrUpdateSavedSearch(ResourceResolver resourceResolver, Map<String, String> requestParameters) throws OmniSearchException {
        String operation = requestParameters.get(":operation");
        try {
            if ("create".equals(operation) || StringUtils.isEmpty((String)operation)) {
                return this.createSavedSearch(resourceResolver, requestParameters);
            }
            if ("update".equals(operation)) {
                return this.updateSavedSearch(resourceResolver, requestParameters);
            }
            LOGGER.warn("Unknown saved search operation: " + operation);
        }
        catch (OmniSearchException e) {
            throw e;
        }
        catch (Exception e) {
            throw new OmniSearchException(e.getMessage());
        }
        return null;
    }

    private Resource createSavedSearch(ResourceResolver resourceResolver, Map<String, String> requestParameters) throws Exception {
        Session session;
        String resourcePath;
        String title = requestParameters.get("title");
        String description = requestParameters.get("description");
        if (StringUtils.isEmpty((String)title)) {
            throw new OmniSearchException("Invalid request, empty title not allowed.");
        }
        boolean autoAdjustTitle = true;
        if (requestParameters.get("autoAdjustTitle") != null) {
            autoAdjustTitle = Boolean.valueOf(requestParameters.get("autoAdjustTitle"));
        }
        Node parentNode = !(session = (Session)resourceResolver.adaptTo(Session.class)).nodeExists(resourcePath = this.getSavedSearchPath(resourceResolver)) ? JcrUtil.createPath((String)resourcePath, (String)"nt:unstructured", (String)"nt:unstructured", (Session)session, (boolean)false) : session.getNode(resourcePath);
        Resource resource = resourceResolver.getResource(resourcePath);
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("jcr:title", title);
        String nodeName = JcrUtil.createValidName((String)title);
        String name = JcrUtil.createValidChildName((Node)parentNode, (String)nodeName);
        if (!autoAdjustTitle && !name.equalsIgnoreCase(nodeName)) {
            throw new OmniSearchException("Invalid request, duplicate collection not allowed.");
        }
        if (!StringUtils.isEmpty((String)description)) {
            params.put("jcr:description", description);
        }
        params.put("jcr:primaryType", "nt:unstructured");
        String resourceType = requestParameters.get("sling:resourceType");
        if (StringUtils.isEmpty((String)resourceType)) {
            resourceType = "sling/collection";
        }
        params.put("sling:resourceType", resourceType);
        ResourceCollectionManager rcMgr = (ResourceCollectionManager)resourceResolver.adaptTo(ResourceCollectionManager.class);
        ResourceCollection rc = rcMgr.createCollection(resource, name, params);
        resourcePath = rc.getPath();
        this.saveQuery(resourceResolver, resourcePath, requestParameters);
        Resource collRes = resourceResolver.getResource(resource, name);
        this.setCreated(collRes);
        this.setLastModified(collRes);
        resourceResolver.commit();
        session.save();
        return collRes;
    }

    private Resource updateSavedSearch(ResourceResolver resourceResolver, Map<String, String> requestParameters) throws Exception {
        String existingTitle;
        String existingDescription;
        String resourcePath = requestParameters.get("resourcePath");
        if (StringUtils.isEmpty((String)resourcePath)) {
            throw new OmniSearchException("Invalid request, empty resource path not allowed.");
        }
        Resource resource = resourceResolver.getResource(resourcePath);
        ResourceCollection collection = (ResourceCollection)resource.adaptTo(ResourceCollection.class);
        if (collection == null) {
            throw new OmniSearchException(MessageFormat.format("Invalid request resource {0} does not represent a saved search.", resource.getPath()));
        }
        String title = requestParameters.get("title");
        String description = requestParameters.get("description");
        ModifiableValueMap mvm = (ModifiableValueMap)resource.adaptTo(ModifiableValueMap.class);
        if (!StringUtils.isEmpty((String)title) && !(existingTitle = (String)mvm.get("jcr:title", (Object)"")).equals(title)) {
            mvm.put((Object)"jcr:title", (Object)title);
        }
        if (!StringUtils.isEmpty((String)description) && !(existingDescription = (String)mvm.get("jcr:description", (Object)"")).equals(description)) {
            mvm.put((Object)"jcr:description", (Object)description);
        }
        this.setLastModified(resource);
        this.saveQuery(resourceResolver, resource.getPath(), requestParameters);
        resourceResolver.commit();
        return resource;
    }

    private String getSavedSearchPath(ResourceResolver resourceResolver) throws RepositoryException {
        Authorizable user = (Authorizable)resourceResolver.adaptTo(Authorizable.class);
        String path = user.getPath() + "/preferences/omnisearch/commerce/" + this.getID();
        return path;
    }

    private Map<String, String> parse(String query) throws UnsupportedEncodingException {
        String[] pairs;
        HashMap<String, String> params = new HashMap<String, String>();
        if (StringUtils.isBlank((String)query)) {
            return params;
        }
        for (String pair : pairs = query.split("&")) {
            int idx = pair.indexOf("=");
            if (idx < 0) continue;
            String name = URLDecoder.decode(pair.substring(0, idx), "UTF-8");
            String value = URLDecoder.decode(pair.substring(idx + 1), "UTF-8");
            params.put(name, value);
        }
        if (params.get("location") == null) {
            params.put("location", this.getID());
        }
        return params;
    }

    private void saveQuery(ResourceResolver resolver, String resPath, Map<String, String> requestParams) throws IOException, RepositoryException {
        Session session = (Session)resolver.adaptTo(Session.class);
        HashMap<String, String> params = new HashMap<String, String>();
        for (String nameObj : requestParams.keySet()) {
            String name = nameObj;
            if (this.ignoreParameter(name)) continue;
            params.put(name, requestParams.get(name));
        }
        PredicateGroup predicates = PredicateGroup.create(params);
        Query query = this.getQueryBuilder().createQuery(predicates, session);
        this.getQueryBuilder().storeQuery(query, resPath + "/" + "savedquery", false, session);
    }

    private boolean ignoreParameter(String parameter) {
        return defaultReqParams.contains(parameter) || parameter.startsWith("jcr:") || parameter.startsWith("sling:") || parameter.startsWith("cq:");
    }

    private void setLastModified(Resource res) {
        ModifiableValueMap contentProps = (ModifiableValueMap)res.adaptTo(ModifiableValueMap.class);
        contentProps.put((Object)"jcr:lastModifiedBy", (Object)res.getResourceResolver().getUserID());
        contentProps.put((Object)"jcr:lastModified", (Object)Calendar.getInstance());
    }

    private void setCreated(Resource res) {
        ModifiableValueMap contentProps = (ModifiableValueMap)res.adaptTo(ModifiableValueMap.class);
        contentProps.put((Object)"jcr:createdBy", (Object)res.getResourceResolver().getUserID());
        contentProps.put((Object)"jcr:created", (Object)Calendar.getInstance());
    }

    abstract QueryBuilder getQueryBuilder();

    static {
        defaultReqParams.add("title");
        defaultReqParams.add("description");
        defaultReqParams.add(":operation");
        defaultReqParams.add("autoAdjustTitle");
        defaultReqParams.add("resourcePath");
    }
}