View Javadoc
1   /**
2    * This file Copyright (c) 2011-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.rendering.template.configured;
35  
36  import info.magnolia.jcr.RuntimeRepositoryException;
37  import info.magnolia.jcr.predicate.AbstractPredicate;
38  import info.magnolia.jcr.util.NodeTypes;
39  import info.magnolia.jcr.util.NodeUtil;
40  import info.magnolia.objectfactory.Components;
41  import info.magnolia.rendering.template.InheritanceConfiguration;
42  
43  import java.util.Arrays;
44  import java.util.Comparator;
45  import java.util.List;
46  
47  import javax.jcr.Node;
48  import javax.jcr.NodeIterator;
49  import javax.jcr.RepositoryException;
50  
51  import org.apache.commons.lang3.StringUtils;
52  
53  /**
54   * Defines behavior for inheritance. Allows for enabling
55   */
56  public class ConfiguredInheritance implements InheritanceConfiguration {
57  
58      public static final String COMPONENTS_ALL = "all";
59      public static final String COMPONENTS_NONE = "none";
60      public static final String COMPONENTS_FILTERED = "filtered";
61  
62      public static final String PROPERTIES_ALL = "all";
63      public static final String PROPERTIES_NONE = "none";
64  
65      private Boolean enabled = false;
66      private String components = COMPONENTS_FILTERED;
67      private String properties = PROPERTIES_ALL;
68      private List<String> nodeTypes = Arrays.asList(NodeTypes.Component.NAME, NodeTypes.Resource.NAME);
69      private Class<? extends AbstractPredicate<Node>> predicateClass;
70      private Class<? extends Comparator<Node>> nodeComparatorClass;
71  
72      @Override
73      public Boolean isEnabled() {
74          return enabled;
75      }
76  
77      public Boolean getEnabled() {
78          return enabled;
79      }
80  
81      public void setEnabled(Boolean enabled) {
82          this.enabled = enabled;
83      }
84  
85      public String getComponents() {
86          return components;
87      }
88  
89      public void setComponents(String components) {
90          this.components = components;
91      }
92  
93      public void setProperties(String properties) {
94          this.properties = properties;
95      }
96  
97      @Override
98      public Boolean isInheritsProperties() {
99          return isEnabled() != null && isEnabled() && StringUtils.equalsIgnoreCase(StringUtils.trim(properties), PROPERTIES_ALL);
100     }
101 
102     @Override
103     public Boolean isInheritsComponents() {
104         return isEnabled() != null && isEnabled() && (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_ALL) || StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_FILTERED));
105     }
106 
107     @Override
108     public AbstractPredicate<Node> getComponentPredicate() {
109         if (isEnabled() == null || !isEnabled()) {
110             return new InheritNothingInheritancePredicate();
111         }
112         if (predicateClass != null) {
113             return Components.newInstance(predicateClass);
114         }
115         if (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_ALL)) {
116             InheritancePredicatecePredicate.html#InheritancePredicate">InheritancePredicate inheritancePredicate = new InheritancePredicate();
117             inheritancePredicate.setNodeTypes(getNodeTypes());
118             return inheritancePredicate;
119         }
120         if (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_FILTERED)) {
121             FilteredInheritancePredicateate.html#FilteredInheritancePredicate">FilteredInheritancePredicate filteredInheritancePredicate = new FilteredInheritancePredicate();
122             filteredInheritancePredicate.setNodeTypes(getNodeTypes());
123             return filteredInheritancePredicate;
124         }
125         return new InheritNothingInheritancePredicate();
126     }
127 
128     public void setPredicateClass(Class<? extends AbstractPredicate<Node>> predicateClass) {
129         this.predicateClass = predicateClass;
130     }
131 
132     @Override
133     public Comparator<Node> getComponentComparator() {
134         if (nodeComparatorClass != null) {
135             return Components.newInstance(nodeComparatorClass);
136         }
137         return new NodeDepthComparator();
138     }
139 
140     public void setNodeComparatorClass(Class<? extends Comparator<Node>> nodeComparatorClass) {
141         this.nodeComparatorClass = nodeComparatorClass;
142     }
143 
144     public List<String> getNodeTypes() {
145         return nodeTypes;
146     }
147 
148     public void setNodeTypes(List<String> nodeTypes) {
149         this.nodeTypes = nodeTypes;
150     }
151 
152     /**
153      * Predicate for component inheritance that includes only nodes with a a property named 'inheritable' that needs to
154      * be present and set to 'true'.
155      *
156      * @deprecated since 5.3.5. Use {@link FilteredInheritancePredicate} instead.
157      */
158     @Deprecated
159     public static class FilteredComponentInheritancePredicate extends AbstractPredicate<Node> {
160 
161         public static final String INHERITED_PROPERTY_NAME = "inheritable";
162 
163         @Override
164         public boolean evaluateTyped(Node node) {
165             try {
166                 return NodeUtil.isNodeType(node, NodeTypes.Component.NAME) && (node.hasProperty(INHERITED_PROPERTY_NAME) && Boolean.parseBoolean(node.getProperty(INHERITED_PROPERTY_NAME).getString()));
167             } catch (RepositoryException e) {
168                 throw new RuntimeRepositoryException(e);
169             }
170         }
171     }
172 
173     /**
174      * Predicate for component inheritance that includes all components.
175      *
176      * @deprecated since 5.3.5. Use {@link InheritancePredicate} instead.
177      */
178     @Deprecated
179     public static class AllComponentsAndResourcesInheritancePredicate extends AbstractPredicate<Node> {
180 
181         @Override
182         public boolean evaluateTyped(Node node) {
183             try {
184                 return NodeUtil.isNodeType(node, NodeTypes.Component.NAME) || NodeUtil.isNodeType(node, NodeTypes.Resource.NAME);
185             } catch (RepositoryException e) {
186                 throw new RuntimeRepositoryException(e);
187             }
188         }
189     }
190 
191     /**
192      * Predicate for component inheritance that includes no components.
193      */
194     public static class InheritNothingInheritancePredicate extends AbstractPredicate<Node> {
195 
196         @Override
197         public boolean evaluateTyped(Node node) {
198             return false;
199         }
200     }
201 
202     /**
203      * Comparator for ordering nodes by depth placing nodes deeper in the hierarchy after those further up and ordering
204      * nodes on the same level by the order they appear as siblings.
205      */
206     public static class NodeDepthComparator implements Comparator<Node> {
207 
208         @Override
209         public int compare(Node lhs, Node rhs) {
210             try {
211                 if (lhs.getDepth() != rhs.getDepth())
212                     return lhs.getDepth() - rhs.getDepth();
213                 return getSiblingIndex(lhs) - getSiblingIndex(rhs);
214             } catch (RepositoryException e) {
215                 throw new RuntimeRepositoryException(e);
216             }
217         }
218 
219         private int getSiblingIndex(Node node) throws RepositoryException {
220             if (node.getDepth() == 0) {
221                 return 0;
222             }
223             int index = 0;
224             NodeIterator nodes = node.getParent().getNodes();
225             while (nodes.hasNext()) {
226                 if (NodeUtil.isSame(node, nodes.nextNode())) {
227                     return index;
228                 }
229                 index++;
230             }
231             return -1;
232         }
233     }
234 }