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

com.adobe.acs.commons.workflow.process.impl.SyntheticWrapperWorkflowProcess Maven / Gradle / Ivy

/*
 * #%L
 * ACS AEM Commons Bundle
 * %%
 * Copyright (C) 2016 Adobe
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package com.adobe.acs.commons.workflow.process.impl;

import com.adobe.acs.commons.fam.ThrottledTaskRunner;
import com.adobe.acs.commons.util.ParameterUtil;
import com.adobe.acs.commons.util.WorkflowHelper;
import com.adobe.acs.commons.util.visitors.ContentVisitor;
import com.adobe.acs.commons.util.visitors.ResourceRunnable;
import com.adobe.acs.commons.workflow.synthetic.SyntheticWorkflowModel;
import com.adobe.acs.commons.workflow.synthetic.SyntheticWorkflowRunner;
import com.adobe.acs.commons.workflow.synthetic.impl.SyntheticWorkflowRunnerAccessor;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
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.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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Component(
        metatype = true,
        label = "ACS AEM Commons - Workflow Process - Synthetic Workflow Wrapper Process",
        description = "Executes an AEM Workflow model as a Synthetic Workflow using FAM"
)
@Properties({
        @Property(
                label = "Workflow Label",
                name = "process.label",
                value = "Synthetic Workflow Wrapper",
                description = "Executes an AEM Workflow model as a Synthetic Workflow (serial execution)"
        )
})
@Service
public class SyntheticWrapperWorkflowProcess implements WorkflowProcess {
    private static final Logger log = LoggerFactory.getLogger(SyntheticWrapperWorkflowProcess.class);
    private static final String ARG_TRAVERSE_TREE = "traverseTree";
    private static final String ARG_SAVE_INTERVAL = "saveInterval";
    private static final String ARG_WORKFLOW_MODEL_ID = "workflowModelId";
    private static final String ARG_THROTTLE = "throttle";

    @Reference
    private SyntheticWorkflowRunnerAccessor syntheticWorkflowRunnerAccessor;

    @Reference
    private ThrottledTaskRunner throttledTaskRunner;

    @Reference
    private WorkflowHelper workflowHelper;

    @Override
    public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaDataMap) throws WorkflowException {
        ResourceResolver resourceResolver = null;
        final SyntheticWorkflowRunner syntheticWorkflowRunner = syntheticWorkflowRunnerAccessor.getSyntheticWorkflowRunner();

        final String payload = (String) workItem.getWorkflowData().getPayload();
        final ProcessArgs processArgs = new ProcessArgs(metaDataMap);

        try {
            resourceResolver = workflowHelper.getResourceResolver(workflowSession);
            final SyntheticWorkflowModel syntheticWorkflowModel = syntheticWorkflowRunner.getSyntheticWorkflowModel(resourceResolver, processArgs.getWorkflowModelId(), true);

            final AtomicInteger count = new AtomicInteger(0);

            // Anonymous inner class to facilitate counting of processed payloads
            final ResourceRunnable syntheticRunnable = new ResourceRunnable() {
                @Override
                public void run(final Resource resource) throws java.lang.Exception {
                    if (processArgs.isThrottle()) {
                        throttledTaskRunner.waitForLowCpuAndLowMemory();
                    }

                    syntheticWorkflowRunner.execute(resource.getResourceResolver(), resource.getPath(), syntheticWorkflowModel, false, false);

                    // Commit as needed
                    if (processArgs.getSaveInterval() > 0
                            && count.incrementAndGet() % processArgs.getSaveInterval() == 0
                            && resource.getResourceResolver().hasChanges()) {
                        resource.getResourceResolver().commit();
                    }
                }
            };

            final ContentVisitor visitor = new ContentVisitor(syntheticRunnable);
            final Resource resource = resourceResolver.getResource(payload);

            if (processArgs.isTraverseTree()) {
                visitor.accept(resource);
            } else {
                syntheticRunnable.run(resource);
            }

            if (processArgs.getSaveInterval() > 0 && resourceResolver.hasChanges()) {
                // Commit any stranglers
                resourceResolver.commit();
            }

            log.info("Synthetic Workflow Wrapper processed [ {} ] total payloads", count.get());
        } catch (Exception e) {
            throw new WorkflowException(e);
        }
    }

    /**
     * ProcessArgs parsed from the WF metadata map
     */
    private  static class ProcessArgs {
        private boolean traverseTree = false;
        private boolean throttle = false;
        private String workflowModelId;
        int saveInterval;

        public ProcessArgs(MetaDataMap map) throws WorkflowException {
            String[] lines = StringUtils.split(map.get(WorkflowHelper.PROCESS_ARGS, ""), System.lineSeparator());
            Map data = ParameterUtil.toMap(lines, "=");

            throttle = Boolean.parseBoolean(data.get(ARG_THROTTLE));
            traverseTree = Boolean.parseBoolean(data.get(ARG_TRAVERSE_TREE));
            workflowModelId = data.get(ARG_WORKFLOW_MODEL_ID);
            try {
                saveInterval = Integer.parseInt(data.get(ARG_SAVE_INTERVAL));
            } catch (NumberFormatException e) {
                log.warn("Could not parse int from [ {} ]", data.get(ARG_SAVE_INTERVAL));
                saveInterval = 100;
            }

            if (StringUtils.isBlank(workflowModelId)) {
                throw new WorkflowException("Unable to parse the workflowModelId from the Workflow Process Args");
            }
        }

        public String getWorkflowModelId() {
            return workflowModelId;
        }

        public boolean isTraverseTree() {
            return traverseTree;
        }

        public int getSaveInterval() {
            return saveInterval;
        }

        public boolean isThrottle() {
            return throttle;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy