AEM 6.5.12.0 - Sites Create CSV Report include Custom Column Components Count

Goal


Extend the Sites CSV Report to configure and include Custom Columns. In this post, the custom column Components Count gives the count of components added on a page...



Component Count Column in Report



Configure Column

                            /apps/wcm/core/content/common/availablecolumns/componentsCount



Configure Page Info Provider In Page Component

                           /apps/weretail/components/structure/page/cq:infoProviders



Select Components Count In Export



Solution


1) Add componentsCount nt:unstructured node in overlay /apps/wcm/core/content/common/availablecolumns with the following properties...

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured">
<componentsCount
jcr:primaryType="nt:unstructured"
jcr:title="Components Count"
columnGroup="Experience AEM"
default="{Boolean}false"
page-info-provider="experienceaem"
page-info-provider-property="componentsCount"
sortable="{Boolean}true"/>
</jcr:root>

2)  Add a filter apps.experienceaem.sites.core.AvailableColumnsDSFilter  to add the custom column in report wizard...

package apps.experienceaem.sites.core;

import com.adobe.granite.ui.components.ds.DataSource;
import com.adobe.granite.ui.components.ds.SimpleDataSource;
import com.adobe.granite.ui.components.ds.ValueMapResource;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.iterators.TransformIterator;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

@Component(
service = Filter.class,
immediate = true,
name = "Experience AEM - Sites CSV Export Custom Data Filter",
property = {
Constants.SERVICE_RANKING + ":Integer=-99",
"sling.filter.scope=COMPONENT",
"sling.filter.resourceTypes=cq/gui/components/siteadmin/admin/listview/columns/datasources/availablecolumnsdatasource"
}
)
public class AvailableColumnsDSFilter implements Filter {
private final Logger logger = LoggerFactory.getLogger(getClass());

public static String EAEM_COLUMNS = "/apps/wcm/core/content/common/availablecolumns";

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
ResourceResolver resolver = slingRequest.getResourceResolver();

chain.doFilter(slingRequest, slingResponse);

DataSource ds = (DataSource)request.getAttribute(DataSource.class.getName());

Resource eaemColumnsRes = resolver.getResource(EAEM_COLUMNS);

if( (ds == null) || (eaemColumnsRes == null)){
return;
}

final List<ValueMap> dsList = new ArrayList<ValueMap>();
Iterator items = ds.iterator();

while (items.hasNext()) {
dsList.add(((ValueMapResource)items.next()).getValueMap());
}

Iterator<Resource> resourceItr = eaemColumnsRes.listChildren();

while(resourceItr.hasNext()){
Resource columnRes = resourceItr.next();
ValueMap columnVM = columnRes.getValueMap();

dsList.add(getCustomColumnVM(columnRes.getName(), columnVM.get("jcr:title", String.class),
columnVM.get("columnGroup", String.class)));
}

ds = new SimpleDataSource(new TransformIterator(dsList.iterator(), new Transformer() {
public Object transform(Object o) {
ValueMap vm = (ValueMap) o;

return new ValueMapResource(slingRequest.getResourceResolver(), new ResourceMetadata(), "nt:unstructured", vm);
}
}));

request.setAttribute(DataSource.class.getName(), ds);
}

private ValueMap getCustomColumnVM(String value, String text, String columnGroup){
ValueMap vm = new ValueMapDecorator(new HashMap<String, Object>());

vm.put("value", value);
vm.put("default", false);
vm.put("text", text);
vm.put("show-selector", "");
vm.put("columnGroup", columnGroup);
vm.put("description-icon", "");

return vm;
}

@Override
public void destroy() {
}
}

3) Add Page info provider apps.experienceaem.sites.core.ComponentCountPageInfoProvider to calculate the component count...

package apps.experienceaem.sites.core;

import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageInfoProvider;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Component(
service = PageInfoProvider.class,
immediate = true,
name = "Experience AEM - Component Count Page Info Provider",
property = {
"pageInfoProviderType=sites.listView.info.provider." + ComponentCountPageInfoProvider.PROVIDER_TYPE
}
)
public class ComponentCountPageInfoProvider implements PageInfoProvider{
public static final String PROVIDER_TYPE = "experienceaem";
public static final String PROVIDER_PROP_COMP_COUNT = "componentsCount";
private static final String SLING_RES_TYPE = "sling:resourceType";

@Override
public void updatePageInfo(SlingHttpServletRequest slingRequest, JSONObject info, Resource resource)
throws JSONException {
List<String> compPaths = new ArrayList<String>();

readAllComponents(resource.getChild("jcr:content"), compPaths);

JSONObject componentsCountJson = new JSONObject();
componentsCountJson.put(PROVIDER_PROP_COMP_COUNT, compPaths.size());

info.put(PROVIDER_TYPE, componentsCountJson);
}

private void readAllComponents(Resource resource, List<String> compPaths){
Iterator<Resource> componentsItr = resource.listChildren();

while(componentsItr.hasNext()){
Resource childRes = componentsItr.next();
ValueMap vm = childRes.getValueMap();

if(StringUtils.isEmpty(vm.get(SLING_RES_TYPE, String.class))){
continue;
}

compPaths.add(childRes.getPath());

readAllComponents(childRes, compPaths);
}
}
}

No comments:

Post a Comment