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

com.adobe.cq.mcm.campaign.profile.ProfileHelper Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2014 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.mcm.campaign.profile;

import com.day.cq.mcm.campaign.ACConnectorException;
import com.day.cq.mcm.campaign.Defs;
import com.day.cq.mcm.campaign.profile.Subscriptions;
import com.day.cq.mcm.campaign.profile.SubscriptionsManager;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.foundation.forms.FormsConstants;
import com.day.cq.wcm.foundation.forms.FormsHelper;
import com.day.cq.wcm.foundation.forms.ValidationInfo;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.scripting.SlingBindings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * Defines helper functions for accessing Campaign profile data (deeply nested format)
 */
public class ProfileHelper {

    private static final String ATTRIB_METADATA = MetaDataNode.class.toString();

    private static final String ATTRIB_PROFILE = Profile.class.toString();

    private static final String ATTRIB_SUBSCRIPTIONS = Subscriptions.class.toString();

    private static final Logger log = LoggerFactory.getLogger(ProfileHelper.class);

    private ProfileHelper() {
        // static helper class
    }

    /**
     * Search the form start for the current form element.
     */
    private static Resource searchFormStart(Resource resource) {
        if (resource.getName().equals(JcrConstants.JCR_CONTENT)) {
            return null;
        }
        if (resource.getPath().lastIndexOf("/") == 0) {
            return null;
        }
        if (ResourceUtil.isA(resource, FormsConstants.RT_FORM_BEGIN)) {
            return resource;
        }
        // first, we have to collect all predecessors
        Resource parent = resource.getParent();
        List predecessor = new ArrayList();
        Iterator children = parent.listChildren();
        while (children.hasNext()) {
            Resource current = children.next();
            if (current.getPath().equals(resource.getPath())) {
                break;
            }
            predecessor.add(current);
        }
        // reverse the order, to get the immediate predecessors first
        Collections.reverse(predecessor);
        // iterate, as soon as we find a form begin, we're done
        // as soon as we find a form end, the form begin is missing for this form
        for (Resource current : predecessor) {
            if (ResourceUtil.isA(current, FormsConstants.RT_FORM_BEGIN)) {
                return current;
            }
            if (ResourceUtil.isA(current, FormsConstants.RT_FORM_END)) {
                return null;
            }
        }
        return searchFormStart(parent);
    }

    public static MetaDataNode getMetaData(SlingHttpServletRequest request)
            throws ACConnectorException {
        MetaDataNode metaData =
                (MetaDataNode) request.getAttribute(ATTRIB_METADATA);
        if (metaData == null) {
            SlingBindings bindings =
                    (SlingBindings) request.getAttribute(SlingBindings.class.getName());
            if (bindings == null) {
                throw new ACConnectorException(
                        "No sling bindings available - utility class is meant to be used"
                        + "from Sling scripts only.");
            }
            MetaDataRetriever retriever =
                    bindings.getSling().getService(MetaDataRetriever.class);
            if (retriever == null) {
                throw new ACConnectorException(
                        "Could not determine 'MetaDataRetriever2' service.");
            }
            Resource resource = request.getResource();
            PageManager pageManager =
                    resource.getResourceResolver().adaptTo(PageManager.class);
            Page page = pageManager.getContainingPage(resource);
            if (page == null) {
                throw new ACConnectorException(
                        "Resource '" + resource.getPath() + "' is not part of a page.");
            }
            metaData = retriever.retrieve(page.adaptTo(Resource.class));
            request.setAttribute(ATTRIB_METADATA, metaData);
        }
        return metaData;
    }

    public static MetaDataNode getMetaDataByPath(SlingHttpServletRequest request,
                                                 String path) throws ACConnectorException {
        MetaDataNode root = getMetaData(request);
        if ((root != null) && (path.startsWith("/"))) {
            String relPath = path.substring(1);
            return root.getChildByPath(relPath);
        }
        return null;
    }

    public static Options getOptions(SlingHttpServletRequest request)
            throws ACConnectorException {

        ValueMap values = request.getResource().adaptTo(ValueMap.class);
        String mapping = values.get("acMapping", String.class);
        String path = ((mapping == null) || mapping.startsWith("/")
                ? mapping : "/" + mapping.replaceAll("\\.", "/"));

        if (path != null) {
            MetaDataNode data = getMetaDataByPath(request, path);
            if (data != null) {
                return (data.hasOptions() ? data.getOptions() : null);
            }
        }
        return null;
    }

    public static Map getOptionsAsMap(SlingHttpServletRequest request) {
        Map optionsMap = null;
        try {
            Options options = getOptions(request);
            if (options != null) {
                optionsMap = new LinkedHashMap(4);
                Iterator values = options.getValues();
                while (values.hasNext()) {
                    OptionValue value = values.next();
                    optionsMap.put(value.getValue(), value.getLabel());
                }
            }
        } catch (ACConnectorException e) {
            log.warn("Could not determine options", e);
        }
        return optionsMap;
    }

    public static Profile getProfile(SlingHttpServletRequest request, String encryptedPK)
            throws ACConnectorException {
        Profile profile = (Profile) request.getAttribute(ATTRIB_PROFILE);
        if (profile == null) {
            MetaDataNode metaData = getMetaData(request);
            SlingBindings bindings =
                    (SlingBindings) request.getAttribute(SlingBindings.class.getName());
            if (bindings == null) {
                throw new ACConnectorException(
                        "No sling bindings available - utility class is meant to be used"
                        + "from Sling scripts only.");
            }
            ProfileRetriever retriever =
                    bindings.getSling().getService(ProfileRetriever.class);
            if (retriever == null) {
                throw new ACConnectorException(
                        "Could not determine 'ProfileRetriever2' service.");
            }
            Resource resource = request.getResource();
            PageManager pageManager =
                    resource.getResourceResolver().adaptTo(PageManager.class);
            Page page = pageManager.getContainingPage(resource);
            if (page == null) {
                throw new ACConnectorException(
                        "Resource '" + resource.getPath() + "' is not part of a page.");
            }
            profile = retriever.load(page.adaptTo(Resource.class), encryptedPK, metaData);
            request.setAttribute(ATTRIB_PROFILE, profile);
        }
        return profile;
    }

    public static String determineEncryptedPK(SlingHttpServletRequest request) {
        log.debug("Determining encrypted PK");
        Resource resource = request.getResource();
        Resource form = searchFormStart(resource);
        if (form == null) {
            log.debug("Form resource not found");
            return null;
        }
        log.debug("Form resource: {}", form.getPath());
        Iterator fields = FormsHelper.getFormElements(form);
        while (fields.hasNext()) {
            Resource field = fields.next();
            log.debug("Processing component '{}' ({})",
                    new String[]{
                            field.getName(), field.getResourceType()
                    });
            if (ResourceUtil.isA(field, Defs.RT_ENCRYPTED_PK)) {
                log.debug("Encrypted PK field found: {}" + field.getName());
                ValueMap values = ResourceUtil.getValueMap(field);
                String urlParameter = values.get("urlParameter", String.class);
                if (urlParameter == null) {
                    log.debug("Missing property 'urlParameter'");
                    return null;
                }
                log.debug("URL parameter for encrypted PK is: {}", urlParameter);
                return request.getParameter(urlParameter);
            }
        }
        return null;
    }

    public static Profile getProfile(SlingHttpServletRequest request)
            throws ACConnectorException {
        // determining the encrypted PK is not "cheap", so we're checking if the profile
        // is already available at the beginning
        Profile profile = (Profile) request.getAttribute(ATTRIB_PROFILE);
        if (profile == null) {
            log.debug("Loading profile data from Adobe Campaign instance.");
            String encryptedPK = determineEncryptedPK(request);
            log.debug("Encrypted primary key: {}", encryptedPK);
            if (encryptedPK != null) {
                profile = getProfile(request, encryptedPK);
            }
        }
        return profile;
    }

    public static MetaDataNode getMetaDataInstance(SlingHttpServletRequest request) {
        Resource resource = request.getResource();
        try {
            log.debug("Profile received successfully,");
            MetaDataNode metaData = getMetaData(request);
            if (metaData == null) {
                return null;
            }
            log.debug("Meta data received successfully,");
            ValueMap values = ResourceUtil.getValueMap(resource);
            String mapping = values.get(Defs.PN_MAPPING, String.class);
            if (mapping == null) {
                return null;
            }
            log.debug("Mapping determined successfully: {}", mapping);
            if (!mapping.startsWith("/")) {
                mapping = "/" + mapping.replaceAll("\\.", "/");
            }
            return getMetaDataByPath(request, mapping);
        } catch (ACConnectorException e) {
            log.warn("Could not determine meta data instance.", e);
        }
        return null;
    }

    public static Object getValue(SlingHttpServletRequest request) {
        Resource resource = request.getResource();
        String name = FormsHelper.getParameterName(resource);

        // determine value from validation info (to keep edited, but invalid values)
        ValidationInfo info = ValidationInfo.getValidationInfo(request);
        if (info != null) {
            log.debug("Validation info found for field '{}'", name);
            String[] valuesArray = info.getValues(name);
            if (valuesArray.length == 1) {
                log.debug("Taking value from validation info: {}", valuesArray[0]);
                return valuesArray[0];
            }
        }

        // determine value from profile, if available
        Object value = null;
        try {
            log.debug("Determining profile value.");
            Profile profile = getProfile(request);
            if (profile != null) {
                MetaDataNode node = getMetaDataInstance(request);
                if (node != null) {
                    log.debug("MetaDataNode: {}", node.getPath());
                    value = profile.getValue(node);
                    log.debug("Profile value: {}", value);
                }
            }
        } catch (ACConnectorException e) {
            log.warn("Could not determine profile", e);
        }
        return value;
    }

    public static List getValuesAsList(SlingHttpServletRequest request) {
        List values = new ArrayList(1);
        Object value = getValue(request);
        if ((value != null) && (value instanceof String)) {
            values.add((String) value);
        }
        return values;
    }

    public static boolean isReconciliationKey(SlingHttpServletRequest request) {
        Resource resource = request.getResource();
        ValueMap values = ResourceUtil.getValueMap(resource);
        return (values != null)
                && "true".equals(values.get(Defs.PN_RECON_KEY, String.class));
    }

    public static boolean getValueAsBoolean(SlingHttpServletRequest request) {
        Object valueObj = getValue(request);
        if (valueObj != null) {
            if (valueObj instanceof Boolean) {
                return (Boolean) valueObj;
            } else if (valueObj instanceof String) {
                String valueStr = (String) valueObj;
                for (String trueValue : Defs.BOOLEAN_TRUE_VALUES) {
                    if (valueStr.equals(trueValue)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static String getBooleanTrue(SlingHttpServletRequest request) {
        Object valueObj = getValue(request);
        if ((valueObj == null) || (!(valueObj instanceof String))) {
            return "true";
        }
        String valueStr = (String) valueObj;
        for (String trueValue : Defs.BOOLEAN_TRUE_VALUES) {
            if (valueStr.equals(trueValue)) {
                return trueValue;
            }
        }
        int i = 0;
        for (String falseValue : Defs.BOOLEAN_FALSE_VALUES) {
            if (valueStr.equals(falseValue)) {
                return Defs.BOOLEAN_TRUE_VALUES[i];
            }
            i++;
        }
        return "true";
    }

    public static String getBooleanFalse(SlingHttpServletRequest request) {
        Object valueObj = getValue(request);
        if ((valueObj == null) || (!(valueObj instanceof String))) {
            return "false";
        }
        String valueStr = (String) valueObj;
        for (String falseValue : Defs.BOOLEAN_FALSE_VALUES) {
            if (valueStr.equals(falseValue)) {
                return falseValue;
            }
        }
        int i = 0;
        for (String trueValue : Defs.BOOLEAN_TRUE_VALUES) {
            if (valueStr.equals(trueValue)) {
                return Defs.BOOLEAN_FALSE_VALUES[i];
            }
            i++;
        }
        return "false";
    }

    public static Subscriptions getSubscriptions(SlingHttpServletRequest req) {
        Subscriptions subscriptions =
                (Subscriptions) req.getAttribute(ATTRIB_SUBSCRIPTIONS);
        if (subscriptions == null) {
            try {
                SlingBindings bindings =
                        (SlingBindings) req.getAttribute(SlingBindings.class.getName());
                if (bindings == null) {
                    throw new ACConnectorException(
                            "No sling bindings available - utility class is meant to be "
                            + "used from Sling scripts only.");
                }
                SubscriptionsManager sm =
                        bindings.getSling().getService(SubscriptionsManager.class);
                if (sm == null) {
                    throw new ACConnectorException(
                            "Could not determine 'SubscriptionsManager' service.");
                }
                Resource resource = req.getResource();
                PageManager pageManager =
                        resource.getResourceResolver().adaptTo(PageManager.class);
                Page page = pageManager.getContainingPage(resource);
                if (page == null) {
                    throw new ACConnectorException(
                            "Resource '" + resource.getPath() + "' is not part of a page.");
                }
                subscriptions = sm.retrieve(page.adaptTo(Resource.class));
                req.setAttribute(ATTRIB_SUBSCRIPTIONS, subscriptions);
            } catch (ACConnectorException ace) {
                log.warn("Could not determine subscriptions: {}", ace.getMessage());
                subscriptions = null;
            }
        }
        return subscriptions;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy