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

com.adobe.cq.contentinsight.ActivityResourceVisitor Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2013 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.contentinsight;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.AbstractResourceVisitor;
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.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.analytics.testandtarget.util.OfferHelper;
import com.day.cq.personalization.TargetedContentManager;

/**
 * An resource visitor that collects all activities (formerly campaigns) that
 * have been published to Adobe Target.
 */
public class ActivityResourceVisitor extends AbstractResourceVisitor {

    private static final Logger log = LoggerFactory.getLogger(ActivityResourceVisitor.class);
    
    private static final String PN_PUBLISH_CAMPAIGN_ID = "publishCampaignId";
    private static final String TARGET_COMPONENT = "cq/personalization/components/target";
    
    private List activities = new ArrayList();

    private String pagePath = "";
    
    private TargetedContentManager targetedContentManager;
    
    public ActivityResourceVisitor(String pagePath, TargetedContentManager targetedContentManager) {
        if (!pagePath.endsWith(JcrConstants.JCR_CONTENT)) {
            pagePath += "/" + JcrConstants.JCR_CONTENT;
        }
        this.pagePath = pagePath;
        this.targetedContentManager = targetedContentManager;
        
        if (targetedContentManager == null) {
            log.warn("No TargetedContentManager available, will not be able to determine campaigns used on the current page!");
        }
    }
    
    /**
     * If resource is of activity resource type, add it to the collection.
     */
    protected void visit(Resource res) {
        ValueMap properties = ResourceUtil.getValueMap(res);
        if(ResourceUtil.isA(res, OfferHelper.RT_CAMPAIGN) && properties.get(PN_PUBLISH_CAMPAIGN_ID, String.class) != null) {
            // only include campaigns that are used on the current page path
            if (matchesPage(res)) {
                activities.add(res);
            }
        }
    }

    /**
     * Return the list of collected activity resources. This list is empty
     * when {@link ActivityResourceVisitor#accept(Resource)} has not been
     * called before.
     */
    public List getActivityResources() {
        return activities;
    }
    
    /**
     * Determines if the given campaign resource is targeted to the visitor's pagePath
     * 
     * @param campaignResource points to the campaign
     * @return {@code Boolean} true if the given campaign is used on the page identified by pagePath
     */
    private boolean matchesPage(Resource campaignResource) {
        boolean matchesPage = false;
        ResourceResolver resolver = campaignResource.getResourceResolver();
        Resource pageRes = resolver.getResource(this.pagePath);
        
        if (pageRes != null && campaignResource != null) {
            String campaignPathPrefix = campaignResource.getParent().getPath() + "/";

            // drill into page's children to see if there's a target component
            // that has associated this campaign
            List targetResources = getTargetComponents(pageRes, null);

            try {
                for (Resource targetResource : targetResources) {
                    // use TargetContentManager API to determine if the campaign
                    // resource is used on the page

                    ValueMap targetResProps = targetResource.adaptTo(ValueMap.class);
                    String locationProp = targetResProps.get("location", null);

                    String locationID = StringUtils.isNotBlank(locationProp)
                            ? locationProp : targetResource.getPath();

                    JSONObject teaserInfo = targetedContentManager.getTeaserInfo(resolver, null, locationID);
                    JSONArray allTeasers = teaserInfo.getJSONArray("allTeasers");
                    for(int i = 0; i < allTeasers.length(); i++) {
                        // check if teaser belongs to currently tested campaign (see CQ-16460)
                        JSONObject teaser = allTeasers.getJSONObject(i);
                        if(teaser.getString("path").startsWith(campaignPathPrefix)) {
                            matchesPage = true;
                            break;
                        }
                    }
                }
            }
            catch (JSONException e) {
                log.error("Could not determine if page {} uses campaign {}!", new Object[]{pageRes.getPath(), campaignResource.getPath()});
                log.error("", e);
            }
        }
        return matchesPage;
    }
    
    /**
     * Finds all children of {@code Resource} rootResource that have the
     * cq/personalization/components/target resource type
     * 
     * @param rootResource
     *            a {@code Resource} where to start looking for target res types
     * @param resList
     *            a {@code List} to add matching resources to. If null} is
     *            passed a new list instance will be automatically created
     *            
     * @return the {@code List} containing target resource types that have the rootResource as an ancestor
     */
    private List getTargetComponents(Resource rootResource, List resList) {
        if (resList == null) {
            resList = new ArrayList();
        }
        
        for(Resource child : rootResource.getChildren()){
            if (child.isResourceType(TARGET_COMPONENT)) {
                resList.add(child);
            } else {
                getTargetComponents(child, resList);
            }
        }
        
        return resList;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy