CustomAnalyticsDataServlet.java 15.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.inherit.HierarchyNodeInheritanceValueMap
 *  com.day.cq.commons.jcr.JcrUtil
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.webservicesupport.ConfigurationManager
 *  com.day.cq.wcm.webservicesupport.ConfigurationManagerFactory
 *  com.google.gson.Gson
 *  com.google.gson.GsonBuilder
 *  javax.servlet.ServletException
 *  org.apache.commons.lang.StringUtils
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  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.api.resource.ResourceUtil
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.api.servlets.SlingAllMethodsServlet
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.analytics.sitecatalyst.impl.servlets;

import com.day.cq.analytics.sitecatalyst.impl.util.ReportConfigUtils;
import com.day.cq.commons.inherit.HierarchyNodeInheritanceValueMap;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.webservicesupport.ConfigurationManager;
import com.day.cq.wcm.webservicesupport.ConfigurationManagerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
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.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Service
@Properties(value={@Property(name="sling.servlet.extensions", value={"config"}), @Property(name="sling.servlet.selectors", value={"customdata"}), @Property(name="sling.servlet.resourceTypes", value={"cq/analytics/components/framework"}), @Property(name="service.description", value={"Servlet used to manage the custom analytics data."}), @Property(name="sling.servlet.methods", value={"GET", "POST", "DELETE"})})
public class CustomAnalyticsDataServlet
extends SlingAllMethodsServlet {
    private static final String PARAM_CONTENT_PATH = "contentpath";
    private static final String PARAM_METRIC = "metric";
    private static final String NAME_REPORT_DESCRIPTION = "reportDescription";
    private static final String NAME_METRICS = "metrics";
    private static final String INDEX_ROOT_NODE_NAME = "analyticsCustomIndex";
    private final Logger log = LoggerFactory.getLogger(CustomAnalyticsDataServlet.class);
    @Reference
    private ConfigurationManagerFactory configurationManagerFactory;

    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        Resource contentResource = null;
        Resource analyticsConfig = request.getResource();
        String[] customAnalyticsData = request.getParameterValues("customanalyticsdata");
        String contentPath = request.getParameter("contentpath");
        if (StringUtils.isNotBlank((String)contentPath)) {
            contentResource = request.getResourceResolver().getResource(contentPath);
        }
        try {
            this.saveSelectedCustomData(customAnalyticsData, analyticsConfig);
            this.updateReportConfigs(contentResource, analyticsConfig);
            this.updateAnalyticsIndexes(analyticsConfig, customAnalyticsData);
        }
        catch (Exception e) {
            this.log.error("Can't persist custom analytics data configuration!", (Throwable)e);
            response.setStatus(500);
            throw new ServletException((Throwable)e);
        }
    }

    protected void doDelete(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        Resource analyticsConfig = request.getResource();
        ResourceResolver resolver = request.getResourceResolver();
        String deleteMetric = request.getParameter("metric");
        String contentPath = request.getParameter("contentpath");
        Resource contentResource = null;
        if (StringUtils.isNotBlank((String)contentPath)) {
            contentResource = request.getResourceResolver().getResource(contentPath);
        }
        try {
            this.removeCustomMetric(deleteMetric, analyticsConfig);
            if (resolver.hasChanges()) {
                resolver.commit();
            }
            this.removeCustomMetricReportConfig(deleteMetric, contentResource, analyticsConfig);
        }
        catch (Exception e) {
            this.log.error("Can't remove custom configured metric!", (Throwable)e);
            response.setStatus(500);
            throw new ServletException((Throwable)e);
        }
    }

    private void updateReportConfigs(Resource contentResource, Resource analyticsConfig) throws IOException {
        ResourceResolver resolver = contentResource.getResourceResolver();
        ConfigurationManager configurationManager = this.configurationManagerFactory.getConfigurationManager(resolver);
        ReportConfigUtils.updateCustomReportConfigs(analyticsConfig.getParent(), contentResource, configurationManager);
        if (resolver.hasChanges()) {
            resolver.commit();
        }
    }

    private void removeCustomMetric(String metricId, Resource analyticsConfigResource) throws PersistenceException {
        Resource customDataRoot = this.getCustomAnalyticsDataConfigurationRoot(analyticsConfigResource, false);
        if (customDataRoot != null) {
            Resource metricConfigResource = customDataRoot.getChild(metricId);
            if (metricConfigResource != null) {
                metricConfigResource.getResourceResolver().delete(metricConfigResource);
            }
        } else {
            this.log.warn("Can't find the configuration node for the custom analytics data!");
        }
    }

    private void removeCustomMetricReportConfig(String metricId, Resource contentResource, Resource analyticsConfig) throws PersistenceException {
        ConfigurationManager configurationManager = this.configurationManagerFactory.getConfigurationManager(contentResource.getResourceResolver());
        Page targetPage = ReportConfigUtils.getPageBySCConfig(contentResource, analyticsConfig, configurationManager);
        if (targetPage != null) {
            ResourceResolver resolver = contentResource.getResourceResolver();
            Resource analyticsReports = ReportConfigUtils.getAnalyticsReportConfigsResource(targetPage);
            List<String> customReportConfigs = Arrays.asList("last30DaysCustomDataReportConfig", "last30DaysPrevCustomDataReportConfig", "thisYearCustomDataReportConfig", "lastYearCustomDataReportConfig", "last90DaysCustomDataReportConfig", "last90DaysPrevCustomDataReportConfig");
            block0 : for (String customReportName : customReportConfigs) {
                Resource customData = analyticsReports.getChild(customReportName);
                Resource metricsCfg = customData.getChild("reportDescription/metrics");
                for (Resource metric : metricsCfg.getChildren()) {
                    ValueMap metricProps = (ValueMap)metric.adaptTo(ValueMap.class);
                    if (!metricId.equalsIgnoreCase((String)metricProps.get("id", (Object)""))) continue;
                    resolver.delete(metric);
                    continue block0;
                }
            }
            if (resolver.hasChanges()) {
                resolver.commit();
            }
        } else {
            this.log.warn("Can't find the first page having " + analyticsConfig.getPath() + " SC configuration!");
        }
    }

    private void saveSelectedCustomData(String[] analyticsData, Resource targetResource) throws PersistenceException {
        ResourceResolver resolver = targetResource.getResourceResolver();
        HierarchyNodeInheritanceValueMap scConfigProperties = new HierarchyNodeInheritanceValueMap(targetResource);
        Resource customDataRoot = this.getCustomAnalyticsDataConfigurationRoot(targetResource, true);
        String metricsJsonStr = (String)scConfigProperties.getInherited("metrics", null);
        List<Object> availableMetrics = Arrays.asList((Object[])new GsonBuilder().create().fromJson(metricsJsonStr, AnalyticsMetric[].class));
        for (Resource customDataConfig : customDataRoot.getChildren()) {
            resolver.delete(customDataConfig);
        }
        if (analyticsData != null) {
            for (String selectedMetricId : analyticsData) {
                AnalyticsMetric metric = this.getMetricById(selectedMetricId, availableMetrics);
                String metricName = JcrUtil.createValidName((String)selectedMetricId);
                Resource customDataConfig2 = resolver.create(customDataRoot, metricName, Collections.singletonMap("jcr:primaryType", "nt:unstructured"));
                ModifiableValueMap dataConfigProps = (ModifiableValueMap)customDataConfig2.adaptTo(ModifiableValueMap.class);
                dataConfigProps.put((Object)"id", (Object)selectedMetricId);
                dataConfigProps.put((Object)"title", (Object)metric.getName());
                dataConfigProps.put((Object)"class", (Object)("analytics-" + metricName));
                dataConfigProps.put((Object)"show-selector", (Object)(".label .analytics-" + metricName));
                dataConfigProps.put((Object)"sort-selector", (Object)(".label .analytics-" + metricName + " .data-column"));
                dataConfigProps.put((Object)"sort-type", (Object)"numeric");
                dataConfigProps.put((Object)"page-info-provider", (Object)"analytics");
                dataConfigProps.put((Object)"columnGroup", (Object)"analytics");
                dataConfigProps.put((Object)"page-info-provider-property", (Object)metricName);
                dataConfigProps.put((Object)"description-icon", (Object)"coral-Icon--automate");
                dataConfigProps.put((Object)"sling:resourceType", (Object)"cq/gui/components/siteadmin/admin/pages/headers/deflt");
            }
        }
        if (resolver.hasChanges()) {
            resolver.commit();
        }
    }

    private Resource getCustomAnalyticsDataConfigurationRoot(Resource analyticsConfigResource, boolean createIfNotExists) throws PersistenceException {
        ResourceResolver resolver = analyticsConfigResource.getResourceResolver();
        Resource customDataRoot = analyticsConfigResource.getChild("customanalyticsdata");
        if (customDataRoot == null && createIfNotExists) {
            customDataRoot = resolver.create(analyticsConfigResource, "customanalyticsdata", Collections.singletonMap("jcr:primaryType", "nt:unstructured"));
        }
        return customDataRoot;
    }

    private AnalyticsMetric getMetricById(String metricId, List<AnalyticsMetric> allMetrics) {
        for (AnalyticsMetric currentMetric : allMetrics) {
            if (!metricId.equalsIgnoreCase(currentMetric.getId())) continue;
            return currentMetric;
        }
        return null;
    }

    private void updateAnalyticsIndexes(Resource analyticsConfigResource, String[] customAnalyticsData) throws PersistenceException {
        if (analyticsConfigResource != null && customAnalyticsData != null && customAnalyticsData.length > 0) {
            String indexesRootPath;
            ResourceResolver resolver = analyticsConfigResource.getResourceResolver();
            Resource indexRootResource = resolver.getResource(indexesRootPath = analyticsConfigResource.getPath() + "/" + "oak:index" + "/" + "analyticsCustomIndex");
            if (indexRootResource == null) {
                HashMap<String, Object> indexRootProps = new HashMap<String, Object>();
                indexRootProps.put("jcr:primaryType", "oak:QueryIndexDefinition");
                indexRootProps.put("name", "analyticsCustomIndex");
                indexRootProps.put("type", "lucene");
                indexRootProps.put("compatVersion", 2);
                indexRootProps.put("async", "async");
                indexRootProps.put("reindex", true);
                ResourceUtil.getOrCreateResource((ResourceResolver)resolver, (String)indexesRootPath, indexRootProps, (String)"nt:unstructured", (boolean)false);
            }
            String indexPropertiesPath = indexesRootPath + "/indexRules/nt:base/properties";
            for (String data : customAnalyticsData) {
                String analyticsDataIndexName = "analytics_" + JcrUtil.createValidName((String)data);
                HashMap<String, Object> indexProps = new HashMap<String, Object>();
                indexProps.put("type", "Long");
                indexProps.put("propertyIndex", true);
                indexProps.put("ordered", true);
                indexProps.put("name", analyticsDataIndexName);
                ResourceUtil.getOrCreateResource((ResourceResolver)resolver, (String)(indexPropertiesPath + "/" + analyticsDataIndexName), indexProps, (String)"nt:unstructured", (boolean)true);
            }
            if (indexRootResource != null) {
                ModifiableValueMap indexRootProps = (ModifiableValueMap)indexRootResource.adaptTo(ModifiableValueMap.class);
                indexRootProps.put((Object)"reindex", (Object)true);
                resolver.commit();
            }
        }
    }

    protected void bindConfigurationManagerFactory(ConfigurationManagerFactory configurationManagerFactory) {
        this.configurationManagerFactory = configurationManagerFactory;
    }

    protected void unbindConfigurationManagerFactory(ConfigurationManagerFactory configurationManagerFactory) {
        if (this.configurationManagerFactory == configurationManagerFactory) {
            this.configurationManagerFactory = null;
        }
    }

    private class AnalyticsMetric {
        private String id;
        private String name;

        private AnalyticsMetric() {
        }

        public String getId() {
            return this.id;
        }

        public String getName() {
            return this.name;
        }

        public boolean equals(Object o) {
            if (o instanceof AnalyticsMetric) {
                return this.id.equalsIgnoreCase(((AnalyticsMetric)o).getId());
            }
            return false;
        }

        public int hashCode() {
            return this.id.hashCode();
        }
    }

}