MboxParagraphPostProcessor.java 10.7 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.wcm.api.Page
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  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.servlets.post.Modification
 *  org.apache.sling.servlets.post.ModificationType
 *  org.apache.sling.servlets.post.SlingPostProcessor
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.analytics.testandtarget.impl;

import com.day.cq.analytics.testandtarget.util.MboxHelper;
import com.day.cq.wcm.api.Page;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
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.servlets.post.Modification;
import org.apache.sling.servlets.post.ModificationType;
import org.apache.sling.servlets.post.SlingPostProcessor;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="Day CQ Analytics Mbox Post Processor", description="Post processes Adobe Target mbox paragraphs and fixes their structure")
@Service(value={SlingPostProcessor.class})
public class MboxParagraphPostProcessor
implements SlingPostProcessor {
    protected final Logger logger;
    @Property(label="Service enabled", description="Enable/disable post processor", boolValue={1})
    public static final String ENABLED = "cq.analytics.testandtarget.mboxparagraphpostprocessor.enabled";
    private final String PAGE_MARKER = "/jcr:content/";
    private static final String MBOX_END_RESOURCE_TYPE_PARAM = "cq:mboxEndResourceType";
    private boolean enabled;

    public MboxParagraphPostProcessor() {
        this.logger = LoggerFactory.getLogger((String)this.getClass().getName());
        this.PAGE_MARKER = "/jcr:content/";
    }

    public void process(SlingHttpServletRequest request, List<Modification> changes) throws Exception {
        if (this.enabled) {
            HashSet<String> fixPaths = new HashSet<String>();
            for (Modification mod : changes) {
                switch (mod.getType()) {
                    case ORDER: 
                    case MOVE: 
                    case COPY: {
                        break;
                    }
                    case MODIFY: 
                    case CREATE: 
                    case DELETE: {
                        int pageEndPos = mod.getSource().indexOf("/jcr:content/");
                        if (pageEndPos == -1) break;
                        String pagePath = mod.getSource().substring(0, pageEndPos);
                        fixPaths.add(pagePath);
                    }
                }
            }
            ResourceResolver resolver = request.getResourceResolver();
            for (String pagePath : fixPaths) {
                this.logger.debug("Checking if resource '{}' is a page", (Object)pagePath);
                Resource resource = resolver.getResource(pagePath);
                if (resource == null || resource.adaptTo(Page.class) == null) {
                    this.logger.debug("resource is not adaptable to Page, skipping");
                    continue;
                }
                String contentPath = pagePath + '/' + "jcr:content";
                this.logger.debug("Checking page for mbox paragraphs {}", (Object)pagePath);
                Resource contentResource = resolver.getResource(contentPath);
                if (contentResource == null) continue;
                this.fixStructure(contentResource);
            }
        }
    }

    private String getStartResourceType() {
        return "cq/personalization/components/mbox/start";
    }

    private String getEndResourceType() {
        return "cq/personalization/components/mbox/end";
    }

    private String getNodeNamePrefix() {
        return "mbox";
    }

    private String getEndResourceType(Resource startContentResource) {
        String propsResourceType = this.getEndResourceType();
        if (startContentResource != null && startContentResource.adaptTo(ValueMap.class) != null) {
            ValueMap properties = (ValueMap)startContentResource.adaptTo(ValueMap.class);
            propsResourceType = (String)properties.get("cq:mboxEndResourceType", (Object)this.getEndResourceType());
        }
        return propsResourceType;
    }

    private void fixStructure(Resource contentResource) throws RepositoryException {
        Iterator rI = ResourceUtil.listChildren((Resource)contentResource);
        while (rI.hasNext()) {
            Resource res = (Resource)rI.next();
            if (ResourceUtil.isA((Resource)res, (String)this.getStartResourceType())) {
                this.checkStructure(res);
                continue;
            }
            if (ResourceUtil.isA((Resource)res, (String)this.getEndResourceType())) {
                this.checkStructure(res);
                continue;
            }
            this.fixStructure(res);
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private Resource checkStructure(Resource rsrc) {
        Resource elementStart;
        if (ResourceUtil.isA((Resource)rsrc, (String)this.getStartResourceType())) {
            Resource startResource = rsrc;
            Iterator iter = ResourceUtil.listChildren((Resource)ResourceUtil.getParent((Resource)rsrc));
            while (!((Resource)iter.next()).getPath().equals(rsrc.getPath())) {
            }
            Resource elementEnd = null;
            Resource nextPar = null;
            boolean stop = false;
            while (iter.hasNext() && elementEnd == null && !stop) {
                Resource current = (Resource)iter.next();
                if (nextPar == null) {
                    nextPar = current;
                }
                if (ResourceUtil.isA((Resource)current, (String)this.getEndResourceType())) {
                    elementEnd = current;
                    continue;
                }
                if (!ResourceUtil.isA((Resource)current, (String)this.getStartResourceType())) continue;
                stop = true;
            }
            if (elementEnd == null) {
                Node parent = (Node)ResourceUtil.getParent((Resource)rsrc).adaptTo(Node.class);
                if (parent != null) {
                    try {
                        String nodeName = this.getNodeNamePrefix() + "_end_" + System.currentTimeMillis();
                        Node node = parent.addNode(nodeName);
                        String resourceType = this.getEndResourceType(startResource);
                        node.setProperty("sling:resourceType", resourceType);
                        if (!resourceType.equals(this.getEndResourceType())) {
                            node.setProperty("sling:resourceSuperType", this.getEndResourceType());
                        }
                        if (nextPar != null) {
                            parent.orderBefore(node.getName(), ResourceUtil.getName((Resource)nextPar));
                        }
                        parent.getSession().save();
                        Iterator i = ResourceUtil.listChildren((Resource)ResourceUtil.getParent((Resource)rsrc));
                        while (i.hasNext()) {
                            Resource r = (Resource)i.next();
                            if (!nodeName.equals(ResourceUtil.getName((Resource)r))) continue;
                            Resource resource = r;
                            return resource;
                        }
                    }
                    catch (RepositoryException re) {
                        this.logger.error("Unable to create missing " + this.getNodeNamePrefix() + " end element for " + this.getNodeNamePrefix() + " start " + (Object)rsrc, (Throwable)re);
                    }
                    finally {
                        try {
                            if (parent.getSession().hasPendingChanges()) {
                                parent.getSession().refresh(false);
                            }
                        }
                        catch (RepositoryException re) {}
                    }
                } else {
                    this.logger.error("Resource is not adaptable to node - unable to add missing " + this.getNodeNamePrefix() + " end element for " + (Object)rsrc);
                }
            }
        } else if (ResourceUtil.isA((Resource)rsrc, (String)this.getEndResourceType()) && (elementStart = MboxHelper.searchStartElement(rsrc)) == null) {
            Node node = (Node)rsrc.adaptTo(Node.class);
            Node parent = (Node)ResourceUtil.getParent((Resource)rsrc).adaptTo(Node.class);
            if (node != null && parent != null) {
                try {
                    node.remove();
                    parent.getSession().save();
                    Resource nextPar = rsrc;
                    return nextPar;
                }
                catch (RepositoryException re) {
                    this.logger.error("Unable to create missing " + this.getNodeNamePrefix() + " end element for " + this.getNodeNamePrefix() + " start " + (Object)rsrc, (Throwable)re);
                }
                finally {
                    try {
                        if (node.getSession().hasPendingChanges()) {
                            node.getSession().refresh(false);
                        }
                    }
                    catch (RepositoryException re) {}
                }
            }
            this.logger.error("Resource is not adaptable to node - unable to remove " + this.getNodeNamePrefix() + " element " + (Object)rsrc);
        }
        return null;
    }

    @Activate
    protected void activate(ComponentContext context) {
        Dictionary configuration = context.getProperties();
        this.enabled = (Boolean)configuration.get("cq.analytics.testandtarget.mboxparagraphpostprocessor.enabled");
        this.logger.debug("Activated, enabled={}", (Object)this.enabled);
    }

}