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             InheritancePredicate inheritancePredicate = new InheritancePredicate();
117             inheritancePredicate.setNodeTypes(getNodeTypes());
118             return inheritancePredicate;
119         }
120         if (StringUtils.equalsIgnoreCase(StringUtils.trim(components), COMPONENTS_FILTERED)) {
121             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     public static class FilteredComponentInheritancePredicate extends AbstractPredicate<Node> {
159 
160         public static final String INHERITED_PROPERTY_NAME = "inheritable";
161 
162         @Override
163         public boolean evaluateTyped(Node node) {
164             try {
165                 return NodeUtil.isNodeType(node, NodeTypes.Component.NAME) && (node.hasProperty(INHERITED_PROPERTY_NAME) && Boolean.parseBoolean(node.getProperty(INHERITED_PROPERTY_NAME).getString()));
166             } catch (RepositoryException e) {
167                 throw new RuntimeRepositoryException(e);
168             }
169         }
170     }
171 
172     /**
173      * Predicate for component inheritance that includes all components.
174      *
175      * @deprecated since 5.3.5. Use {@link InheritancePredicate} instead.
176      */
177     public static class AllComponentsAndResourcesInheritancePredicate extends AbstractPredicate<Node> {
178 
179         @Override
180         public boolean evaluateTyped(Node node) {
181             try {
182                 return NodeUtil.isNodeType(node, NodeTypes.Component.NAME) || NodeUtil.isNodeType(node, NodeTypes.Resource.NAME);
183             } catch (RepositoryException e) {
184                 throw new RuntimeRepositoryException(e);
185             }
186         }
187     }
188 
189     /**
190      * Predicate for component inheritance that includes no components.
191      */
192     public static class InheritNothingInheritancePredicate extends AbstractPredicate<Node> {
193 
194         @Override
195         public boolean evaluateTyped(Node node) {
196             return false;
197         }
198     }
199 
200     /**
201      * Comparator for ordering nodes by depth placing nodes deeper in the hierarchy after those further up and ordering
202      * nodes on the same level by the order they appear as siblings.
203      */
204     public static class NodeDepthComparator implements Comparator<Node> {
205 
206         @Override
207         public int compare(Node lhs, Node rhs) {
208             try {
209                 if (lhs.getDepth() != rhs.getDepth())
210                     return lhs.getDepth() - rhs.getDepth();
211                 return getSiblingIndex(lhs) - getSiblingIndex(rhs);
212             } catch (RepositoryException e) {
213                 throw new RuntimeRepositoryException(e);
214             }
215         }
216 
217         private int getSiblingIndex(Node node) throws RepositoryException {
218             if (node.getDepth() == 0) {
219                 return 0;
220             }
221             int index = 0;
222             NodeIterator nodes = node.getParent().getNodes();
223             while (nodes.hasNext()) {
224                 if (NodeUtil.isSame(node, nodes.nextNode())) {
225                     return index;
226                 }
227                 index++;
228             }
229             return -1;
230         }
231     }
232 }