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

com.day.cq.wcm.msm.commons.BaseAction 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.day.cq.wcm.msm.commons;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import org.apache.jackrabbit.JcrConstants;
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.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.io.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.wcm.api.NameConstants;
import com.day.cq.wcm.api.WCMException;
import com.day.cq.wcm.msm.api.ActionConfig;
import com.day.cq.wcm.msm.api.LiveAction;
import com.day.cq.wcm.msm.api.LiveActionFactory;
import com.day.cq.wcm.msm.api.LiveRelationship;

/**
 * Base implementation for the {@code LiveAction} interface.
 * 
 * This abstract class offers some basic configuration tasks for building a
 * {@code LiveAction} and also default implementations for the deprecated
 * methods. It will speed up the implementation of a {@code LiveAction}
 * by only implementing the handles and doExecute abstract methods.
 * 
 */
public abstract class BaseAction implements LiveAction {

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

    // configuration map for this action
    private final ValueMap config;
    
    // the action factory used to build this action
    private final BaseActionFactory liveActionFactory;
    
    /**
     * An action should only be constructed via {@link LiveActionFactory#createAction(Resource) LiveActionFactory.createAction}.
     * It has protected access to allow sub-classing.
     * 
     * Builds a base action using a {@code ValueMap} containing the action
     * configuration.
     * 
     * @param config the {@code ValueMap} with the action configuration as supplied by {@link LiveActionFactory#createAction(Resource) LiveActionFactory.createAction}
     * @param liveActionFactory the {@code BaseActionFactory} used to build this action
     */
    protected BaseAction(ValueMap config, BaseActionFactory liveActionFactory) {
        this.config = config;
        this.liveActionFactory = liveActionFactory;
    }
    
    /**
     * The name of this action.
     * It must match the {@link LiveActionFactory#createsAction() createsAction() from LiveActionFactory}
     * that creates this action
     */
    public String getName() {
        return getClass().getSimpleName();
    }
    
    /**
     * Check for any preconditions this action needs for execution.
     * Will be called by {@link BaseAction#execute(Resource, Resource, LiveRelationship, boolean, boolean) BaseAction.execute}
     * to determine if the action's preconditions are met. If preconditions are not met this should return false, in which case
     * the {@link BaseAction#doExecute(Resource, Resource, LiveRelationship, boolean) doExecute()} will not be called.
     * 
     * @param source The Resource to roll-out.
     * @param target The Resource to receive modification.
     * @param relation LiveRelationship between the two given Resources
     * @param resetRollout True if rollout is run in reset mode
     * @return boolean flag indicating if this action should go ahead with the
     *         execution. if false no action will be performed as the {@link BaseAction#doExecute(Resource, Resource, LiveRelationship, boolean) doExecute()}
     *         method will not be called.
     * @throws RepositoryException
     * @throws WCMException
     */
    protected abstract boolean handles(Resource source, Resource target, LiveRelationship relation, boolean resetRollout) throws RepositoryException, WCMException;

    /**
     * The actual method that performs the action. Should be implemented by extending classes to provide the action execution functionality.
     * Will only be called if the {@link BaseAction#handles(Resource, Resource, LiveRelationship, boolean) handles()} check returns true
     * 
     * @param source The Resource to roll-out.
     * @param target The Resource to receive modification.
     * @param relation LiveRelationship between the two given Resources
     * @param resetRollout True if rollout is run in reset mode
     * @throws RepositoryException
     * @throws WCMException
     */
    protected abstract void doExecute(Resource source, Resource target, LiveRelationship relation, boolean resetRollout) throws RepositoryException, WCMException;
    
    /**
     * Executes the current action.
* - checks the preconditions using {@link BaseAction#handles(Resource, Resource, LiveRelationship, boolean) handles()}
* - if preconditions are met the {@link BaseAction#doExecute(Resource, Resource, LiveRelationship, boolean) doExecute()} is called
* - changes will be saved automatically if the autoSave flag is set to true *
* This method needs that at least one of the {@code Resource} parameters (source,target) to be non-null when used in conjunction with * the autoSave flag since a {@code ResourceResolver} will need to be obtained to save the changes. * A {@code NonExistingResource} should be used when dealing with non existing resources. */ public void execute(Resource source, Resource target, LiveRelationship relation, boolean autoSave, boolean isResetRollout) throws WCMException { try { if (handles(source, target, relation, isResetRollout)) { doExecute(source, target, relation, isResetRollout); log.debug("Executed action {} on rolling out source {} to target {}", new String[] {getName(), relation.getSourcePath(), relation.getTargetPath()}); if (autoSave && (resourceHasNode(source) || resourceHasNode(target))) { ResourceResolver resourceResolver = source == null ? target.getResourceResolver() : source.getResourceResolver(); if (resourceResolver != null) { if (resourceResolver.hasChanges()) { resourceResolver.commit(); } } } } else { log.debug("{} did not act on request to roll-out {} to {}: precondition was not met", new String[] { getName(), relation.getSourcePath(), relation.getTargetPath() }); } } catch (RepositoryException e) { throw new WCMException(e); } catch (PersistenceException pe) { throw new WCMException(pe); } } protected ValueMap getConfig() { return this.config; } protected BaseActionFactory getActionFactory() { return this.liveActionFactory; } /** * Simple test if a Resource exists and is adaptable to {@link Node} * * @param resource in question * @return true if the Resource is non-synthetic and can be adapted to a Node */ public static boolean resourceHasNode(Resource resource) { return resource != null && resource.adaptTo(Node.class) != null; } /** * Checks if the given Node is considered a {@link com.day.cq.wcm.api.Page Page}
* The check considers the {@value NameConstants#NT_PAGE} and its primary child the * {@value JcrConstants#JCR_CONTENT} Node as being a Page. * This is as the {@link com.day.cq.wcm.msm.api.RolloutManager} calls the {@link LiveAction LiveActions} * with the later. As modifications should only be written to its content. Pages should not be changed. *

* Pages are considered an aggregate of all the Nodes and sub-graph at its {@value JcrConstants#JCR_CONTENT} Node. * Thus Services may require special treatment of them. Eg. Replication, Revisions are bound to Pages. * * @param node to Test * @return true if the Node's NodeType is of {@value NameConstants#NT_PAGE} or it is the * Page's {@value JcrConstants#JCR_CONTENT} Node * @throws RepositoryException on errors accessing the Repository */ public static boolean isPage(Node node) throws RepositoryException { if (node == null) { return false; } boolean isPage = node.isNodeType(NameConstants.NT_PAGE); if (!isPage) { isPage = JcrConstants.JCR_CONTENT.equals(node.getName()) && node.getDefinition().getDeclaringNodeType().isNodeType(NameConstants.NT_PAGE); } return isPage; } @Deprecated public void execute(ResourceResolver resolver, LiveRelationship relation, ActionConfig config, boolean autoSave) throws WCMException { execute(resolver, relation, config, autoSave, false); } @Deprecated public void execute(ResourceResolver resolver, LiveRelationship relation, ActionConfig config, boolean autoSave, boolean isResetRollout) throws WCMException { ValueMap valueMap = new ValueMapDecorator(new HashMap()); valueMap.putAll(config.getProperties()); LiveAction liveAction = liveActionFactory.newActionInstance(valueMap); liveAction.execute(resolver.getResource(relation.getSourcePath()), resolver.getResource(relation.getTargetPath()), relation, autoSave, isResetRollout); } @Deprecated public String getParameterName() { String paramName = config != null ? config.get("cq.wcm.msm.action.parameter", "") : ""; return paramName; } @Deprecated public int getRank() { return 0; } @Deprecated public String getTitle() { String title = config != null ? config.get("jcr:title", getName()) : ""; return title; } @Deprecated public String[] getPropertiesNames() { Set propertySet = new HashSet(); if (config != null) { for (String key : config.keySet()) { // skip properties starting with {cq:, sling:, jcr:} in order to keep backward compatibility // also skip properties that don't resolve to a String if (key != null && !key.matches("^(cq|sling|jcr):.*") && config.get(key, String.class) != null) { propertySet.add(key); } } } return propertySet.toArray(new String[propertySet.size()]); } @Deprecated public void write(JSONWriter jsonWriter) throws JSONException { jsonWriter.object(); jsonWriter.key("name").value(getName()); jsonWriter.key("parameter").value(getParameterName()); jsonWriter.key("title").value(getTitle()); jsonWriter.key("rank").value(getRank()); jsonWriter.key("properites"); jsonWriter.array(); for(String prop: getPropertiesNames()) { jsonWriter.value(prop); } jsonWriter.endArray(); jsonWriter.endObject(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy