SmartListManagerImpl.java 18.3 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.cq.social.srp.SocialResourceProvider
 *  com.adobe.cq.social.srp.config.SocialResourceConfiguration
 *  com.adobe.cq.social.ugc.api.Constraint
 *  com.adobe.cq.social.ugc.api.ConstraintGroup
 *  com.adobe.cq.social.ugc.api.PathConstraint
 *  com.adobe.cq.social.ugc.api.PathConstraintType
 *  com.adobe.cq.social.ugc.api.SearchResults
 *  com.adobe.cq.social.ugc.api.UgcFilter
 *  com.adobe.cq.social.ugc.api.UgcSearch
 *  com.adobe.cq.social.ugc.api.UgcSort
 *  com.adobe.cq.social.ugc.api.UgcSort$Direction
 *  com.adobe.cq.social.ugc.api.ValueConstraint
 *  com.adobe.cq.social.ugcbase.SocialUtils
 *  com.adobe.granite.security.user.UserProperties
 *  com.day.cq.commons.jcr.JcrUtil
 *  javax.jcr.RepositoryException
 *  org.apache.commons.lang.RandomStringUtils
 *  org.apache.commons.lang.StringUtils
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.resource.ModifiableValueMap
 *  org.apache.sling.api.resource.PersistenceException
 *  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.osgi.service.event.Event
 *  org.osgi.service.event.EventAdmin
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.commerce.impl.smartlist;

import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.smartlist.SmartList;
import com.adobe.cq.commerce.api.smartlist.SmartListManager;
import com.adobe.cq.commerce.impl.smartlist.SmartListImpl;
import com.adobe.cq.social.srp.SocialResourceProvider;
import com.adobe.cq.social.srp.config.SocialResourceConfiguration;
import com.adobe.cq.social.ugc.api.Constraint;
import com.adobe.cq.social.ugc.api.ConstraintGroup;
import com.adobe.cq.social.ugc.api.PathConstraint;
import com.adobe.cq.social.ugc.api.PathConstraintType;
import com.adobe.cq.social.ugc.api.SearchResults;
import com.adobe.cq.social.ugc.api.UgcFilter;
import com.adobe.cq.social.ugc.api.UgcSearch;
import com.adobe.cq.social.ugc.api.UgcSort;
import com.adobe.cq.social.ugc.api.ValueConstraint;
import com.adobe.cq.social.ugcbase.SocialUtils;
import com.adobe.granite.security.user.UserProperties;
import com.day.cq.commons.jcr.JcrUtil;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.jcr.RepositoryException;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
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.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SmartListManagerImpl
implements SmartListManager {
    protected static final String SMART_LIST_RESOURCE_TYPE_VALUE = "commerce/smartlist";
    protected static final String PN_PRODUCT_COLLECTION_TYPE = "commerce.collection.type";
    protected static final String SMART_LIST_BASE_PATH = "/etc/commerce/smartlists";
    private static final Logger LOGGER = LoggerFactory.getLogger(SmartListManagerImpl.class);
    private static final String FILTER_PERSONAL = "personal";
    private static final String FILTER_FRIENDS = "friends";
    private final ResourceResolver resourceResolver;
    private final SlingHttpServletRequest request;
    private final ResourceCollectionManager resourceCollectionManager;
    private final SocialUtils socialUtils;
    private final UgcSearch ugcSearch;
    private final EventAdmin eventAdmin;

    public SmartListManagerImpl(SlingHttpServletRequest request, SocialUtils socialUtils, UgcSearch ugcSearch, EventAdmin eventAdmin) throws CommerceException {
        this.request = request;
        this.resourceResolver = request.getResourceResolver();
        this.resourceCollectionManager = (ResourceCollectionManager)this.resourceResolver.adaptTo(ResourceCollectionManager.class);
        this.socialUtils = socialUtils;
        this.ugcSearch = ugcSearch;
        this.eventAdmin = eventAdmin;
        Resource smartListBaseResource = this.getRootResource(this.resourceResolver);
        SocialResourceConfiguration storageConfig = socialUtils.getStorageConfig(smartListBaseResource);
        SocialResourceProvider srp = socialUtils.getConfiguredProvider(smartListBaseResource);
        srp.setConfig(storageConfig);
    }

    @Override
    public SmartList getSmartList(String path) {
        try {
            Resource rcResource = this.resourceResolver.getResource(path);
            if (rcResource == null) {
                rcResource = this.resourceResolver.getResource(this.getRootResource(this.resourceResolver), path);
            }
            if (rcResource == null) {
                return null;
            }
            if (!rcResource.isResourceType("commerce/smartlist")) {
                return null;
            }
            SmartListImpl smartList = new SmartListImpl(rcResource, this.eventAdmin);
            if (this.canRead(smartList)) {
                return smartList;
            }
        }
        catch (CommerceException e) {
            LOGGER.error("Cannot get smart list collection " + path, (Throwable)e);
        }
        return null;
    }

    @Override
    public List<SmartList> getSmartLists(String filter) {
        ArrayList<SmartList> smartLists = new ArrayList<SmartList>();
        try {
            UgcFilter ugcFilter = null;
            if (filter == null || StringUtils.equals((String)filter, (String)"personal")) {
                ugcFilter = this.getPersonalListsFilter();
            } else if (StringUtils.equals((String)filter, (String)"friends")) {
                ugcFilter = this.getFriendsListsFilter();
            }
            if (ugcFilter != null) {
                SearchResults results = this.ugcSearch.find(null, this.resourceResolver, ugcFilter, 0, 100, false);
                for (Resource resultRes : results.getResults()) {
                    if (resultRes.isResourceType("commerce/smartlist")) {
                        LOGGER.debug("found smart list collection {}", (Object)resultRes.getPath());
                        smartLists.add(new SmartListImpl(resultRes, this.eventAdmin));
                        continue;
                    }
                    LOGGER.debug("Search returned {} but resource is not {}", (Object)resultRes.getPath(), (Object)"commerce/smartlist");
                }
            }
        }
        catch (RepositoryException e) {
            LOGGER.error("Cannot get smart lists, search failed", (Throwable)e);
        }
        catch (CommerceException e) {
            LOGGER.error("Cannot get smart lists", (Throwable)e);
        }
        return smartLists;
    }

    @Override
    public SmartList createSmartList(String name) throws CommerceException {
        return this.createSmartList(name, new HashMap<String, Object>());
    }

    @Override
    public SmartList createSmartList(String name, Map<String, Object> properties) throws CommerceException {
        try {
            if (properties == null) {
                properties = new HashMap<String, Object>();
            }
            properties.put("sling:resourceType", "commerce/smartlist");
            if (properties.get("commerce.collection.type") == null) {
                properties.put("commerce.collection.type", "product-based");
            }
            if (properties.get("jcr:primaryType") == null) {
                properties.put("jcr:primaryType", "nt:unstructured");
            }
            if (properties.get("userIdentifier") == null) {
                String userIdentifier = this.getUserIdentifier();
                properties.put("userIdentifier", userIdentifier);
            }
            if (properties.get("smartlist_privacy_s") == null) {
                properties.put("smartlist_privacy_s", SmartList.Privacy.PERSONAL.name());
            }
            ResourceCollection resourceCollection = this.resourceCollectionManager.createCollection(this.getRootResource(this.resourceResolver), this.getUniqueSmartListName(name), properties);
            this.resourceResolver.commit();
            LOGGER.debug("Smart list resource collection created {}", (Object)resourceCollection.getName());
            this.logEvent("com/adobe/cq/commerce/smartlist/ADDED", resourceCollection.getPath());
            return new SmartListImpl(this.resourceResolver.getResource(resourceCollection.getPath()), this.eventAdmin);
        }
        catch (PersistenceException e) {
            throw new CommerceException("Cannot create a smart list collection  " + name, (Throwable)e);
        }
    }

    @Override
    public void updateSmartList(String path, Map<String, Object> properties) throws CommerceException {
        if (path == null) {
            throw new CommerceException("Cannot update the smart list as it is undefined.");
        }
        if (!this.isOwner(path)) {
            throw new CommerceException("Cannot update the smart list " + path);
        }
        try {
            Resource slResource = this.getRootResource(this.resourceResolver).getChild(path);
            String slResPath = slResource.getPath();
            ModifiableValueMap currentProps = (ModifiableValueMap)slResource.adaptTo(ModifiableValueMap.class);
            currentProps.putAll(properties);
            this.resourceResolver.commit();
            this.logEvent("com/adobe/cq/commerce/smartlist/MODIFIED", slResPath);
        }
        catch (PersistenceException e) {
            throw new CommerceException("Cannot update the collection at " + path, (Throwable)e);
        }
    }

    @Override
    public void deleteSmartList(String path) throws CommerceException {
        boolean deleted;
        if (path == null) {
            throw new CommerceException("Cannot delete the smart list as it is undefined.");
        }
        if (!this.isOwner(path)) {
            throw new CommerceException("Cannot delete the smart list " + path);
        }
        try {
            Resource slResource = this.getRootResource(this.resourceResolver).getChild(path);
            String slResPath = slResource.getPath();
            deleted = this.resourceCollectionManager.deleteCollection(slResource);
            this.resourceResolver.commit();
            this.logEvent("com/adobe/cq/commerce/smartlist/DELETED", slResPath);
        }
        catch (PersistenceException e) {
            throw new CommerceException("Cannot delete the collection at " + path);
        }
        if (!deleted) {
            throw new CommerceException("Cannot delete the collection at " + path);
        }
    }

    @Override
    public void makeSmartListDefault(String path) throws CommerceException {
        if (path == null) {
            throw new CommerceException("Cannot mark the smart list as it is undefined.");
        }
        if (!this.isOwner(path)) {
            throw new CommerceException("Cannot mark the smart list " + path + " as default");
        }
        try {
            List<SmartList> smartLists = this.getSmartLists("personal");
            Resource rootResource = this.getRootResource(this.resourceResolver);
            for (SmartList list : smartLists) {
                Resource listResource = rootResource.getChild(list.getPath());
                ModifiableValueMap listResourceModifiableValueMap = (ModifiableValueMap)listResource.adaptTo(ModifiableValueMap.class);
                listResourceModifiableValueMap.remove((Object)"smartlist_default_b");
            }
            HashMap<String, Boolean> properties = new HashMap<String, Boolean>();
            properties.put("smartlist_default_b", Boolean.TRUE);
            Resource smartListResource = this.getRootResource(this.resourceResolver).getChild(path);
            ModifiableValueMap currentProps = (ModifiableValueMap)smartListResource.adaptTo(ModifiableValueMap.class);
            currentProps.putAll(properties);
            this.resourceResolver.commit();
            LOGGER.debug("{} marked as default", (Object)path);
        }
        catch (PersistenceException e) {
            throw new CommerceException("Cannot update the collection at " + path);
        }
    }

    /*
     * Enabled force condition propagation
     * Lifted jumps to return sites
     */
    @Override
    public void shareSmartList(String path, Map<String, Object> properties) throws CommerceException {
        if (path == null) {
            throw new CommerceException("Cannot change sharing status of smart list as it is undefined.");
        }
        if (!this.isOwner(path)) {
            throw new CommerceException("Cannot change sharing status of smart list " + path);
        }
        try {
            Resource slResource = this.getRootResource(this.resourceResolver).getChild(path);
            ModifiableValueMap currentProps = (ModifiableValueMap)slResource.adaptTo(ModifiableValueMap.class);
            if (properties != null) {
                if (!properties.containsKey("smartlist_privacy_s")) throw new CommerceException("Cannot update the sharing status for " + path + " sharing privacy status is missing");
                currentProps.putAll(properties);
            } else {
                currentProps.put((Object)"smartlist_privacy_s", (Object)SmartList.Privacy.PERSONAL.name());
            }
            this.resourceResolver.commit();
            return;
        }
        catch (PersistenceException e) {
            throw new CommerceException("Cannot update the sharing status for " + path, (Throwable)e);
        }
    }

    private Resource getRootResource(ResourceResolver resourceResolver) throws CommerceException {
        Resource baseResource = resourceResolver.getResource("/etc/commerce/smartlists");
        if (baseResource == null) {
            throw new CommerceException("Cannot read root resource /etc/commerce/smartlists");
        }
        String rootResourcePath = this.socialUtils.resourceToUGCStoragePath(baseResource);
        Resource rootResource = resourceResolver.getResource(rootResourcePath);
        if (rootResource == null) {
            HashMap<String, String> properties = new HashMap<String, String>();
            properties.put("jcr:primaryType", "sling:Folder");
            SocialResourceProvider srp = this.socialUtils.getConfiguredProvider(baseResource);
            try {
                rootResource = srp.create(resourceResolver, rootResourcePath, properties);
                resourceResolver.commit();
            }
            catch (PersistenceException e) {
                throw new CommerceException("Cannot create root resource for " + baseResource.getPath(), (Throwable)e);
            }
        }
        return rootResource;
    }

    private UgcFilter getPersonalListsFilter() throws CommerceException {
        UgcFilter filter = new UgcFilter();
        ConstraintGroup cg = new ConstraintGroup();
        cg.addConstraint((Constraint)new ValueConstraint("sling:resourceType", (Object)"commerce/smartlist"));
        cg.addConstraint((Constraint)new PathConstraint("/etc/commerce/smartlists", PathConstraintType.IsDescendantNode));
        String userIdentifier = this.getUserIdentifier();
        if (StringUtils.isNotEmpty((String)userIdentifier)) {
            cg.and((Constraint)new ValueConstraint("userIdentifier", (Object)userIdentifier));
        }
        filter.and((Constraint)cg);
        filter.addSort(new UgcSort("smartlist_default_b", UgcSort.Direction.Desc));
        filter.addSort(new UgcSort("timestamp", UgcSort.Direction.Desc));
        return filter;
    }

    private UgcFilter getFriendsListsFilter() throws CommerceException {
        UgcFilter filter = new UgcFilter();
        ConstraintGroup cg = new ConstraintGroup();
        cg.addConstraint((Constraint)new ValueConstraint("sling:resourceType", (Object)"commerce/smartlist"));
        cg.addConstraint((Constraint)new PathConstraint("/etc/commerce/smartlists", PathConstraintType.IsDescendantNode));
        String userIdentifier = "todo";
        if (StringUtils.isNotEmpty((String)"todo")) {
            cg.and((Constraint)new ValueConstraint("userIdentifier", (Object)"todo"));
        }
        filter.and((Constraint)cg);
        filter.addSort(new UgcSort("smartlist_default_b", UgcSort.Direction.Desc));
        filter.addSort(new UgcSort("timestamp", UgcSort.Direction.Desc));
        return filter;
    }

    private String getUserIdentifier() throws CommerceException {
        String userIdentifier;
        UserProperties up = (UserProperties)this.request.adaptTo(UserProperties.class);
        String string = userIdentifier = up == null ? null : up.getAuthorizableID();
        if (userIdentifier == null) {
            throw new CommerceException("No user identifier available");
        }
        return userIdentifier;
    }

    private boolean isOwner(String smartListPath) {
        return this.isOwner(this.getSmartList(smartListPath));
    }

    private boolean isOwner(SmartList smartList) {
        try {
            if (smartList != null && StringUtils.equals((String)this.getUserIdentifier(), (String)smartList.getOwner())) {
                return true;
            }
        }
        catch (CommerceException e) {
            LOGGER.error("Owner check failed, only the smart list owner is allowed to execute this operation", (Throwable)e);
        }
        return false;
    }

    private boolean canRead(SmartList smartList) {
        return smartList != null && (this.isOwner(smartList) || !smartList.getPrivacy().equals((Object)SmartList.Privacy.PERSONAL));
    }

    private String getUniqueSmartListName(String title) {
        return JcrUtil.createValidName((String)title, (String[])JcrUtil.HYPHEN_LABEL_CHAR_MAPPING) + "-" + RandomStringUtils.randomAlphanumeric((int)6);
    }

    protected void logEvent(String eventName, String smartListPath) {
        if (this.eventAdmin != null) {
            Hashtable<String, String> eventProperties = new Hashtable<String, String>();
            eventProperties.put("smartlist", smartListPath);
            eventProperties.put("userid", this.resourceResolver.getUserID());
            this.eventAdmin.postEvent(new Event(eventName, eventProperties));
        }
    }
}