com.adobe.granite.ui.components.FilteringResourceWrapper Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2016 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.adobe.granite.ui.components;
import java.util.Iterator;
import javax.annotation.Nonnull;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.iterators.FilterIterator;
import org.apache.commons.collections4.iterators.TransformIterator;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.api.resource.ValueMap;
/**
* A ResourceWrapper that filters its descendant resources based on
* {@code granite:hide} BooleanEL property.
*
*
* This wrapper needs to be applied to the container resource, such as the page
* root resource, and the dialog root resource.
*
*
*
* It is also smart enough to handle include component. In that case, if the
* resource type is {@code granite/ui/components/coral/foundation/include}, the
* included resource will also be wrapped by this class, allowing the descendant
* resources of the included resource to use {@code granite:hide} property.
*
*
*
* For example given the following content structure:
*
*
*
*
* + /mycontainer
* - sling:resourceType = "my/container"
* + item1
* - sling:resourceType = "my/item"
* + item2
* - sling:resourceType = "my/item"
* - granite:hide = true
* + item3
* - sling:resourceType = "my/item"
* + item4
* - sling:resourceType = "granite/ui/components/coral/foundation/include"
* - path = "/mycontainer2"
*
* + /mycontainer2
* - sling:resourceType = "my/container2"
* + item1
* - sling:resourceType = "my/item"
* + item2
* - sling:resourceType = "my/item"
* - granite:hide = true
*
*
*
*
* Assuming that {@code my/container} resource type implementation uses
* {@code FilteringResourceWrapper} to wrap its resource ({@code /mycontainer}
* resource), {@code /mycontainer/item2} and {@code /mycontainer2/item2} will be
* excluded during traversal transparently, as if they are not there in the
* first place.
*
*/
public class FilteringResourceWrapper extends ResourceWrapper {
@Nonnull
private ExpressionResolver expressionResolver;
@Nonnull
private SlingHttpServletRequest request;
public FilteringResourceWrapper(@Nonnull Resource resource, @Nonnull ExpressionResolver expressionResolver,
@Nonnull SlingHttpServletRequest request) {
super(resource);
this.expressionResolver = expressionResolver;
this.request = request;
}
@Override
public Resource getChild(String relPath) {
Resource child = super.getChild(relPath);
if (child == null || !isVisible(child)) {
return null;
}
return new FilteringResourceWrapper(child, expressionResolver, request);
}
@Override
public Iterator listChildren() {
return new TransformIterator<>(new FilterIterator<>(super.listChildren(), new Predicate() {
@Override
public boolean evaluate(Resource o) {
return isVisible(o);
}
}), new Transformer() {
@SuppressWarnings("null")
@Override
public Resource transform(Resource o) {
return new FilteringResourceWrapper(o, expressionResolver, request);
}
});
}
@Override
public Iterable getChildren() {
return new Iterable() {
@Override
public Iterator iterator() {
return listChildren();
}
};
}
@Override
public boolean hasChildren() {
if (!super.hasChildren()) {
return false;
}
return listChildren().hasNext();
}
@Override
public String getResourceType() {
if (isResourceType("granite/ui/components/coral/foundation/include")) {
return "granite/ui/components/coral/foundation/includewrapper";
}
return super.getResourceType();
}
private boolean isVisible(Resource r) {
ValueMap vm = r.getValueMap();
ExpressionHelper ex = new ExpressionHelper(expressionResolver, request);
return !ex.getBoolean(vm.get("granite:hide", "false"));
}
}