ScreensSavedSearchHandler.java 13 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
 *  javax.jcr.UnsupportedRepositoryOperationException
 *  org.apache.commons.collections.IteratorUtils
 *  org.apache.commons.lang.StringUtils
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  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
 */
package com.adobe.cq.screens.dcc.impl;

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.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
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;

@Component(immediate=1)
@Service(value={SavedSearchHandler.class})
public class ScreensSavedSearchHandler
implements SavedSearchHandler {
    private static final String LOCATION = "screens";
    private static final String PN_CQ_SAVEDQUERY = "savedquery";
    private static final String NT_CQ_PREFERENCES = "screens/search";
    private static final String PARAM_SEP = "&";
    private static final String NAME_VALUE_SEPARATOR = "=";
    private static final String REQUEST_PARAMETER_TITLE = "title";
    private static final String REQUEST_PARAMETER_DESC = "description";
    private static final String REQUEST_PARAM_AUTO_ADJUST_TITLE = "autoAdjustTitle";
    private static final String REQUEST_PARAM_RESOURCE_PATH = "resourcePath";
    static final String CREATE_COMMAND = "create";
    static final String UPDATE_COMMAND = "update";
    private static final String LOCATION_PARAM = "location";
    private static final Set<String> defaultReqParams = new HashSet<String>();
    @Reference
    private QueryBuilder queryBuilder;

    public String getID() {
        return "screens";
    }

    public Iterator<Resource> getSavedSearches(ResourceResolver resourceResolver, long limit, long offset) {
        String userHome;
        HashMap<String, String> map = new HashMap<String, String>();
        Session session = (Session)resourceResolver.adaptTo(Session.class);
        Authorizable user = (Authorizable)resourceResolver.adaptTo(Authorizable.class);
        try {
            userHome = user.getPath() + "/" + "screens/search";
        }
        catch (RepositoryException e) {
            return Collections.emptyIterator();
        }
        map.put("path", userHome);
        map.put("type", "nt:unstructured");
        map.put("property", "sling:resourceType");
        map.put("property.value", "sling/collection");
        Query query = this.queryBuilder.createQuery(PredicateGroup.create(map), session);
        SearchResult result = query.getResult();
        List resultList = IteratorUtils.toList((Iterator)result.getResources());
        return resultList.iterator();
    }

    public Map<String, String> getSavedSearchParameters(ResourceResolver resourceResolver, String path) {
        Resource resource;
        Resource resource2 = resource = StringUtils.isEmpty((String)path) ? null : 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.queryBuilder.loadQuery(queryPath, session);
            String queryParams = storedQuery.getPredicates().toURL();
            return ScreensSavedSearchHandler.parse(queryParams);
        }
        catch (Exception e) {
            return Collections.emptyMap();
        }
    }

    public Resource createOrUpdateSavedSearch(ResourceResolver resourceResolver, Map<String, String> requestParameters) throws OmniSearchException {
        String title = requestParameters.get("title");
        String description = requestParameters.get("description");
        String resourcePath = requestParameters.containsKey("resourcePath") ? requestParameters.get("resourcePath") : "";
        try {
            String existingDescription;
            String existingTitle;
            Authorizable user = (Authorizable)resourceResolver.adaptTo(Authorizable.class);
            Session session = (Session)resourceResolver.adaptTo(Session.class);
            ResourceCollectionManager rcMgr = (ResourceCollectionManager)resourceResolver.adaptTo(ResourceCollectionManager.class);
            String userHome = user.getPath() + "/" + "screens/search";
            if (StringUtils.isEmpty((String)resourcePath)) {
                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.nodeExists(resourcePath = userHome) ? 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);
                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);
                session.save();
                return collRes;
            }
            Resource resource = resourceResolver.getResource(resourcePath);
            if (resource == null) {
                throw new OmniSearchException("Invalid request, invalid resource path not allowed.");
            }
            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()));
            }
            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();
            if (session.hasPendingChanges()) {
                session.save();
            }
            return resource;
        }
        catch (UnsupportedRepositoryOperationException e) {
            throw new OmniSearchException(e.getMessage());
        }
        catch (Exception e) {
            throw new OmniSearchException(e.getMessage());
        }
    }

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

    private static 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) {
                return params;
            }
            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", "screens");
        }
        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 name : requestParams.keySet()) {
            if (this.ignoreParameter(name)) continue;
            params.put(name, requestParams.get(name));
        }
        PredicateGroup predicates = PredicateGroup.create(params);
        Query query = this.queryBuilder.createQuery(predicates, session);
        this.queryBuilder.storeQuery(query, resPath + "/" + "savedquery", false, session);
    }

    private boolean ignoreParameter(String key) {
        return defaultReqParams.contains(key) || key.startsWith("jcr:") || key.startsWith("sling:") || key.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());
    }

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

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

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