Quantcast
Channel: Experiencing Adobe Experience Manager (AEM, CQ)
Viewing all articles
Browse latest Browse all 525

AEM 65 - Content Copy using Workflow Dialog Participant Step

$
0
0

Goal


A sample workflow with dialog participant step for selecting destination folder from a list of options in dropdown. Subfolders under a specific root folder eg. /content/dam are shown in the dropdown

Demo | Package Install | Github


Dialog Path in Participant Step



Dialog in CRX



Dialog in Complete Work Item



Solution


1) Create a datasource /apps/eaem-content-copy-dialog-pariticipant-step/dialogs/folders-ds/folders-ds.jsp for showing the folders in dropdown. Here the root folder was set to /content/dam, but the logic can be adjusted to return a folder list based on usecase

<%@include file="/libs/granite/ui/global.jsp"%>

<%@ page import="com.adobe.granite.ui.components.ds.DataSource" %>
<%@ page import="com.adobe.granite.ui.components.ds.ValueMapResource" %>
<%@ page import="org.apache.sling.api.wrappers.ValueMapDecorator" %>
<%@ page import="com.adobe.granite.ui.components.ds.SimpleDataSource" %>
<%@ page import="org.apache.commons.collections.iterators.TransformIterator" %>
<%@ page import="org.apache.commons.collections.Transformer" %>
<%@ page import="org.apache.sling.api.resource.*" %>
<%@ page import="java.util.*" %>

<%
String ROOT_PATH = "/content/dam";

final ResourceResolver resolver = resourceResolver;

Resource rootPath = resolver.getResource(ROOT_PATH);

List<Resource> qualifiedParents = new ArrayList<Resource>();

rootPath.listChildren().forEachRemaining(r -> {
if(r.getName().equals("jcr:content")){
return;
}

qualifiedParents.add(r);
});

DataSource ds = new SimpleDataSource(new TransformIterator(qualifiedParents.iterator(), new Transformer() {
public Object transform(Object o) {
Resource resource = (Resource) o;
ValueMap vm = new ValueMapDecorator(new HashMap<String, Object>()),
tvm = resource.getValueMap();

vm.put("value", resource.getPath());
vm.put("text", tvm.get("jcr:content/jcr:title", tvm.get("jcr:title", resource.getName())));

return new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm);
}
}));

request.setAttribute(DataSource.class.getName(), ds);
%>

2) Create the dialog /apps/eaem-content-copy-dialog-pariticipant-step/dialogs/content-copy-dialog to show in Inbox console work item Complete Workflow Item

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Experience AEM Content Copy"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<parent
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldDescription="Select Parent Folder"
fieldLabel="Parent Folder"
name="parentFolder">
<datasource
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/eaem-content-copy-dialog-pariticipant-step/dialogs/folders-ds"
addNone="{Boolean}true"/>
</parent>
</items>
</column>
</items>
</content>
</jcr:root>


3) Add the dialog path in Dialog Participant Step of workflow model e.g. /conf/global/settings/workflow/models/experience-aem-content-copy



4) Create a process step e.g. apps.experienceaem.assets.ContentCopyTask to read the parent folder path set in parentFolder of previous step (dialog drop down)

package apps.experienceaem.assets;

import com.adobe.granite.workflow.PayloadMap;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.commons.util.DamUtil;
import com.day.cq.workflow.metadata.MetaDataMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.*;
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 org.apache.sling.jcr.resource.api.JcrResourceConstants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.Session;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;

@Component(
immediate = true,
service = {WorkflowProcess.class},
property = {
"process.label = Experience AEM Content Copy Task"
}
)
public class ContentCopyTask implements WorkflowProcess {
protected final Logger log = LoggerFactory.getLogger(this.getClass());

private static final String DIALOG_PARTICIPANT_NODE_ID = "node1";
private static final String DESTINATION_PATH = "parentFolder";

@Reference
private ResourceResolverFactory resolverFactory;

@Override
public void execute(WorkItem item, WorkflowSession wfSession, MetaDataMap args) throws WorkflowException {
try {
Session session = wfSession.getSession();
ResourceResolver resolver = getResourceResolver(session);

Asset payload = getAssetFromPayload(item, resolver);

if(payload == null){
log.error("Empty payload, nothing to copy");
return;
}

String destinationPath = getDestinationPathForCopy(item, resolver);

if(StringUtils.isEmpty(destinationPath)){
log.error("Destination path empty for copyign content - " + payload.getPath());
return;
}

Node copiedPath = JcrUtil.copy(payload.adaptTo(Node.class), resolver.getResource(destinationPath).adaptTo(Node.class), null);

log.debug("Copied Path - " + copiedPath);

session.save();
} catch (Exception e) {
log.error("Failed to copy content", e);
}
}

private String getDestinationPathForCopy(WorkItem item, ResourceResolver resolver) throws Exception{
String wfHistoryPath = item.getWorkflow().getId() + "/history";

Iterator<Resource> historyItr = resolver.getResource(wfHistoryPath).listChildren();
ValueMap metaVM = null;

Resource resource, itemResource;
String nodeId, destinationPath = "";

while(historyItr.hasNext()){
resource = historyItr.next();

itemResource = resource.getChild("workItem");

nodeId = itemResource.getValueMap().get("nodeId", "");

if(!nodeId.equals(DIALOG_PARTICIPANT_NODE_ID)){
continue;
}

metaVM = itemResource.getChild("metaData").getValueMap();

destinationPath = metaVM.get(DESTINATION_PATH, "");

break;
}

return destinationPath;
}

public Asset getAssetFromPayload(final WorkItem item, final ResourceResolver resolver) throws Exception{
Asset asset = null;

if (!item.getWorkflowData().getPayloadType().equals(PayloadMap.TYPE_JCR_PATH)) {
return null;
}

final String path = item.getWorkflowData().getPayload().toString();
final Resource resource = resolver.getResource(path);

if (null != resource) {
asset = DamUtil.resolveToAsset(resource);
} else {
log.error("getAssetFromPayload: asset [{}] in payload of workflow [{}] does not exist.", path,
item.getWorkflow().getId());
}

return asset;
}

private ResourceResolver getResourceResolver(final Session session) throws LoginException {
return resolverFactory.getResourceResolver( Collections.<String, Object>
singletonMap(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session));
}
}





Viewing all articles
Browse latest Browse all 525

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>