/**
* This file Copyright (c) 2011-2012 Magnolia International
* Ltd. (http://www.magnolia-cms.com). All rights reserved.
*
*
* This file is dual-licensed under both the Magnolia
* Network Agreement and the GNU General Public License.
* You may elect to use one or the other of these licenses.
*
* This file is distributed in the hope that it will be
* useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
* Redistribution, except as permitted by whichever of the GPL
* or MNA you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or
* modify this file under the terms of the GNU General
* Public License, Version 3, as published by the Free Software
* Foundation. You should have received a copy of the GNU
* General Public License, Version 3 along with this program;
* if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 2. For the Magnolia Network Agreement (MNA), this file
* and the accompanying materials are made available under the
* terms of the MNA which accompanies this distribution, and
* is available at http://www.magnolia-cms.com/mna.html
*
* Any modifications to this file must keep this entire header
* intact.
*
*/
package info.magnolia.rendering.template.configured;
import info.magnolia.jcr.RuntimeRepositoryException;
import info.magnolia.jcr.predicate.AbstractPredicate;
import info.magnolia.jcr.util.NodeTypes;
import info.magnolia.jcr.util.NodeUtil;
import info.magnolia.objectfactory.Components;
import info.magnolia.rendering.template.InheritanceConfiguration;
import java.util.Comparator;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import org.apache.commons.lang.StringUtils;
/**
* Defines behavior for inheritance. Allows for enabling
*
* @version $Id$
*/
public class ConfiguredInheritance implements InheritanceConfiguration {
public static final String COMPONENTS_ALL = "all";
public static final String COMPONENTS_NONE = "none";
public static final String COMPONENTS_FILTERED = "filtered";
public static final String PROPERTIES_ALL = "all";
public static final String PROPERTIES_NONE = "none";
private Boolean enabled = false;
private String components = COMPONENTS_FILTERED;
private String properties = PROPERTIES_ALL;
private Class<? extends AbstractPredicate<Node>> predicateClass;
private Class<? extends Comparator<Node>> nodeComparatorClass;
@Override
public Boolean isEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public void setComponents(String components) {
this.components = components;
}
public void setProperties(String properties) {
this.properties = properties;
}
@Override
public Boolean isInheritsProperties() {
return isEnabled() != null && isEnabled() && StringUtils.equalsIgnoreCase(StringUtils.trim(properties), PROPERTIES_ALL);
}
@Override
public Boolean isInheritsComponents() {
return isEnabled() != null && isEnabled() && (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_ALL) || StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_FILTERED));
}
@Override
public AbstractPredicate<Node> getComponentPredicate() {
if (isEnabled() == null || !isEnabled()) {
return new InheritNothingInheritancePredicate();
}
if (predicateClass != null) {
return Components.newInstance(predicateClass);
}
if (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_ALL)) {
return new AllComponentsAndResourcesInheritancePredicate();
}
if (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_FILTERED)) {
return new FilteredComponentInheritancePredicate();
}
return new InheritNothingInheritancePredicate();
}
public void setPredicateClass(Class<? extends AbstractPredicate<Node>> predicateClass) {
this.predicateClass = predicateClass;
}
@Override
public Comparator<Node> getComponentComparator() {
if (nodeComparatorClass != null) {
return Components.newInstance(nodeComparatorClass);
}
return new NodeDepthComparator();
}
public void setNodeComparatorClass(Class<? extends Comparator<Node>> nodeComparatorClass) {
this.nodeComparatorClass = nodeComparatorClass;
}
/**
* Predicate for component inheritance that includes only nodes with a a property named 'inheritable' that needs to
* be present and set to 'true'.
*/
public static class FilteredComponentInheritancePredicate extends AbstractPredicate<Node> {
public static final String INHERITED_PROPERTY_NAME = "inheritable";
@Override
public boolean evaluateTyped(Node node) {
try {
return NodeUtil.isNodeType(node, NodeTypes.Component.NAME) && (node.hasProperty(INHERITED_PROPERTY_NAME) && Boolean.parseBoolean(node.getProperty(INHERITED_PROPERTY_NAME).getString()));
} catch (RepositoryException e) {
throw new RuntimeRepositoryException(e);
}
}
}
/**
* Predicate for component inheritance that includes all components.
*/
public static class AllComponentsAndResourcesInheritancePredicate extends AbstractPredicate<Node> {
@Override
public boolean evaluateTyped(Node node) {
try {
return NodeUtil.isNodeType(node, NodeTypes.Component.NAME) || NodeUtil.isNodeType(node, NodeTypes.Resource.NAME);
} catch (RepositoryException e) {
throw new RuntimeRepositoryException(e);
}
}
}
/**
* Predicate for component inheritance that includes no components.
*/
public static class InheritNothingInheritancePredicate extends AbstractPredicate<Node> {
@Override
public boolean evaluateTyped(Node node) {
return false;
}
}
/**
* Comparator for ordering nodes by depth placing nodes deeper in the hierarchy after those further up and ordering
* nodes on the same level by the order they appear as siblings.
*/
public static class NodeDepthComparator implements Comparator<Node> {
@Override
public int compare(Node lhs, Node rhs) {
try {
if (lhs.getDepth() != rhs.getDepth())
return lhs.getDepth() - rhs.getDepth();
return getSiblingIndex(lhs) - getSiblingIndex(rhs);
} catch (RepositoryException e) {
throw new RuntimeRepositoryException(e);
}
}
private int getSiblingIndex(Node node) throws RepositoryException {
if (node.getDepth() == 0) {
return 0;
}
int index = 0;
NodeIterator nodes = node.getParent().getNodes();
while (nodes.hasNext()) {
if (NodeUtil.isSame(node, nodes.nextNode())) {
return index;
}
index++;
}
return -1;
}
}
}