All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.social.review.client.api.AbstractReviewCollection Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2012 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.adobe.cq.social.review.client.api;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.NonExistingResource;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.cq.social.commons.comments.api.AbstractCommentCollection;
import com.adobe.cq.social.commons.comments.api.CommentCollection;
import com.adobe.cq.social.commons.comments.api.CommentCollectionConfiguration;
import com.adobe.cq.social.commons.comments.listing.CommentSocialComponentListProviderManager;
import com.adobe.cq.social.scf.ClientUtilities;
import com.adobe.cq.social.scf.QueryRequestInfo;
import com.adobe.cq.social.scf.SocialComponentFactory;
import com.adobe.cq.social.scf.SocialComponentFactoryManager;
import com.adobe.cq.social.tally.client.api.ResponseValue;
import com.adobe.cq.social.tally.client.api.TallyException;
import com.adobe.cq.social.tally.client.api.RatingSocialComponent;
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.ValueConstraint;
import com.adobe.cq.social.ugcbase.SocialUtils;

public abstract class AbstractReviewCollection
    extends AbstractCommentCollection implements ReviewCollectionSocialComponent {

    protected final ResourceResolver resolver;
    protected Resource ugcResource;
    protected final String authorizableUserID;
    protected Map ratings;
    protected RatingSocialComponent overallRating;
    private final UgcSearch search;
    private List> allowedRatings;
    private String[] requiredRatingTitles;
    private boolean includeHistogram = false;

    protected static final String NAME_KEY = "name";
    protected static final String REQUIRED_KEY = "required";

    /** Logger for this class. */
    private static final Logger LOG = LoggerFactory.getLogger(AbstractReviewCollection.class);

    /**
     * Construct a {@link CommentCollection} using the specified {@link Resource} which should be the root of the
     * collection.
     * @param resource the resource where the CommentCollection is located
     * @param listProviderManager the list provider manager
     * @param clientUtils the clientUtilities instance
     */
    public AbstractReviewCollection(final Resource resource, final ClientUtilities clientUtils,
        final CommentSocialComponentListProviderManager listProviderManager) {
        this(resource, clientUtils, QueryRequestInfo.DEFAULT_QUERY_INFO_FACTORY.create(), listProviderManager);
    }

    public AbstractReviewCollection(final Resource resource, final ClientUtilities clientUtils,
        final CommentSocialComponentListProviderManager listProviderManager, final UgcSearch search) {
        this(resource, clientUtils, QueryRequestInfo.DEFAULT_QUERY_INFO_FACTORY.create(), listProviderManager, search);
    }

    public AbstractReviewCollection(final Resource resource, final ClientUtilities clientUtils,
        final QueryRequestInfo queryInfo, final CommentSocialComponentListProviderManager listProviderManager) {
        this(resource, clientUtils, queryInfo, listProviderManager, null);
    }

    /**
     * Construct a {@link CommentCollection} using the specified {@link Resource} which should be the root of the
     * collection with specified pagination for the children listing.
     * @param resource the resource where the CommentCollection is located
     * @param clientUtils the clientUtilities instance
     * @param queryInfo the query parameters, if any
     * @param listProviderManager the list provider manager
     * @param search the ugc search service
     */
    public AbstractReviewCollection(final Resource resource, final ClientUtilities clientUtils,
        final QueryRequestInfo queryInfo, final CommentSocialComponentListProviderManager listProviderManager,
        final UgcSearch search) {
        super(resource, clientUtils, queryInfo, listProviderManager);
        this.resolver = resource.getResourceResolver();
        String path = clientUtils.getSocialUtils().resourceToUGCStoragePath(resource);
        this.ugcResource = resolver.getResource(path);
        if (this.ugcResource == null) {
            this.ugcResource = new NonExistingResource(resolver, path);
        }
        this.search = search;
        this.authorizableUserID = getLoggedInUser();
        this.ratings = getRatings(clientUtils);
        this.overallRating = getOverallRating(clientUtils);
    }

    private RatingSocialComponent getOverallRating(final ClientUtilities clientUtils) {
        final String overallRatingTitle =
            (this.requiredRatingTitles == null) ? ReviewConstants.PATH_OVERALL_RATING : requiredRatingTitles[0];
        Resource baseResource = ugcResource.getParent();
        if (baseResource != null) {
            // assume the first required rating is the overall rating or equivalent
            baseResource = baseResource.getChild(this.resource.getName() + "_" + overallRatingTitle);
        } else {
            final Resource parentResource =
                this.resolver.getResource(StringUtils.substringBeforeLast(ugcResource.getPath(), "/"));
            if (parentResource != null) {
                baseResource = parentResource.getChild(this.resource.getName() + "_" + overallRatingTitle);
            } else {
                baseResource = null;
            }
        }
        return getRatingSocialComponentFromResource(baseResource, clientUtils);
    }

    public RatingSocialComponent getOverallRating() {
        return this.overallRating;
    }

    private Map getRatings(final ClientUtilities clientUtils) {
        final Map results = new HashMap();
        final Resource parentResource = ugcResource.getParent();
        Iterator children = Collections.emptyList().iterator();
        if (parentResource != null) {
            children = parentResource.getChildren().iterator();
        } else {
            // If a parent is not available use the ugcResource as it might be a dynamic include
            // This should cause a list children to be invoked inside the SRP which will get all the children. Might
            // need to change when we get
            // atomic incrementers.
            List ratingResources = new ArrayList();
            String resourceName = StringUtils.substringAfterLast(ugcResource.getPath(), "/");
            String resourceBasePath = StringUtils.substringBeforeLast(ugcResource.getPath(), "/");
            List> ratings = getAllowedRatings();
            // If we're using the new search constructors we can skip the slower iteration pattern and save some round
            // trips
            // to the storage layer.
            if (search != null) {
                UgcFilter resourceTypeAndParentFilter = new UgcFilter();
                // final ConstraintGroup pathGroup = new ConstraintGroup();
                // pathGroup.or(new PathConstraint(resourceBasePath, PathConstraintType.IsChildNode));
                // pathGroup.or(new PathConstraint(StringUtils.substringBeforeLast(this.resource.getPath(), "/"),
                // PathConstraintType.IsChildNode));
                resourceTypeAndParentFilter.addConstraint(new PathConstraint(resourceBasePath,
                    PathConstraintType.IsDescendantNode));
                ValueConstraint resourceTypeConstraint =
                    new ValueConstraint(SocialUtils.PN_SLING_RESOURCETYPE,
                        RatingSocialComponent.RATING_RESOURCE_TYPE);
                resourceTypeAndParentFilter.addConstraint(resourceTypeConstraint);
                try {
                    SearchResults childrenResources =
                        search.find(null, ugcResource.getResourceResolver(), resourceTypeAndParentFilter, 0,
                            ratings.size(), false);
                    ratingResources = childrenResources.getResults();
                    children = ratingResources.iterator();
                } catch (final RepositoryException e) {
                    LOG.error("Could not perform search to find ratings for {}", ugcResource.getPath());
                }
            } else {
                for (Map rating : ratings) {
                    final String childResourcePath = resourceBasePath + "/" + resourceName + "_" + rating.get("name");
                    Resource child = ugcResource.getResourceResolver().getResource(childResourcePath);
                    if (child != null) {
                        ratingResources.add(child);
                    }
                }
                children = ratingResources.iterator();
            }
        }
        while (children.hasNext()) {
            final Resource child = children.next();
            if (resolver.isResourceType(child, RatingSocialComponent.RATING_RESOURCE_TYPE)) {
                final String name = StringUtils.substringAfterLast(child.getName(), "_");
                final RatingSocialComponent rating = getRatingSocialComponentFromResource(child, clientUtils);
                results.put(name, rating);
            }
        }
        return results;
    }

    private boolean isRatingAllowed(final String name) {
        final List> allowed = getAllowedRatings();
        for (final Map map : allowed) {
            if (map != null && StringUtils.equals(map.get(NAME_KEY), name)) {
                return true;
            }
        }
        return false;
    }

    private RatingSocialComponent getRatingSocialComponentFromResource(final Resource resource,
        final ClientUtilities clientUtils) {
        if (resource != null) {
            final SocialComponentFactoryManager scfMgr = clientUtils.getSocialComponentFactoryManager();
            if (scfMgr != null) {
                final SocialComponentFactory scf = scfMgr.getSocialComponentFactory(resource);
                if (scf != null) {
                    return (RatingSocialComponent) scf.getSocialComponent(resource);
                }
            }
        }
        return null;
    }

    private String getLoggedInUser() {
        if (this.resolver == null) {
            return null;
        }
        return this.resolver.adaptTo(Session.class).getUserID();
    }

    @Override
    public String getName() {
        return getProperty(ReviewConstants.NAME_PROPERTY, String.class);
    }

    @Override
    public Long getTotalNumberOfResponses() {
        return new Long(getTotalSize());
    }

    @Override
    public Map getCurrentUserResponse() throws TallyException, RepositoryException {
        final Map results = new HashMap();
        final ResponseValue comment = new ResponseValue() {
            @Override
            public String getResponseValue() {
                return getCurrentUserComment();
            }
        };
        results.put(ReviewConstants.KEY_COMMENT, comment);
        if (overallRating != null && overallRating.getCurrentUserResponse() != null) {
            results.put(overallRating.getName(), overallRating.getCurrentUserResponse());
            return results;
        } else {
            return null;
        }
    }

    private String getCurrentUserComment() {
        // TODO: currently comment is not needed by client side
        return "";
    }

    @Override
    public Map getRatings() {
        return ratings;
    }

    @Override
    public Map getRatingAverages() {
        final Map results = new LinkedHashMap();
        for (final Map map : allowedRatings) {
            if (map != null && map.get(NAME_KEY) != null) {
                final String name = map.get(NAME_KEY);
                if (ratings.get(name) != null) {
                    results.put(name, ratings.get(name).getFormattedAverageRating());
                } else {
                    results.put(name, null);
                }
            }
        }
        return results;
    }

    private void buildAllowedRatings() {
        Resource allowedRatingResource = null;
        if (this.resource.isResourceType(ReviewConstants.REVIEW_SUMMARY_RESOURCE_TYPE)) {
            final ValueMap summaryVM = ResourceUtil.getValueMap(this.resource);
            if (summaryVM.containsKey(ReviewConstants.REVIEW_PATH_PROPERTY)) {
                allowedRatingResource =
                    resolver.resolve((String) summaryVM.get(ReviewConstants.REVIEW_PATH_PROPERTY));
            }
        }

        if (allowedRatingResource == null) {
            allowedRatingResource = resolver.resolve(this.resource.getPath());
        }

        final ValueMap values =
            (allowedRatingResource.adaptTo(ValueMap.class) != null) ? allowedRatingResource.adaptTo(ValueMap.class)
                : clientUtils.getDesignProperties(allowedRatingResource, ReviewConstants.REVIEWS_RESOURCE_TYPE);
        final String[] ratings =
            values.get(ReviewConstants.ALLOWED_RATINGS_PROPERTY, new String[]{ReviewConstants.PATH_OVERALL_RATING});
        this.allowedRatings = new ArrayList>(ratings.length);
        this.requiredRatingTitles =
            values.get(ReviewConstants.REQUIRED_RATINGS_PROPERTY, new String[]{ReviewConstants.PATH_OVERALL_RATING});
        final List requiredList = Arrays.asList(requiredRatingTitles);
        for (final String subrating : ratings) {
            final Map map = new HashMap(2);
            map.put(NAME_KEY, subrating);
            if (requiredList.contains(subrating)) {
                map.put(REQUIRED_KEY, "true");
            }
            this.allowedRatings.add(map);
        }
    }

    @Override
    public List> getAllowedRatings() {
        if (null == this.allowedRatings) {
            this.buildAllowedRatings();
        }
        return this.allowedRatings;
    }

    @Override
    public boolean isCompositeRating() {
        if (getAllowedRatings() == null) {
            return false;
        }
        return getAllowedRatings().size() != 1;
    }

    @Override
    public boolean isIncludeHistogram() {
        return includeHistogram;
    }

    protected void setIncludeHistogram(final boolean include) {
        includeHistogram = include;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy