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