001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.support; 017 018import javax.jcr.Node; 019import javax.jcr.Property; 020import javax.jcr.PropertyType; 021import javax.jcr.RepositoryException; 022import javax.jcr.version.OnParentVersionAction; 023 024import org.apache.commons.collections.Predicate; 025import org.apache.commons.collections.PredicateUtils; 026import org.apache.commons.lang.ArrayUtils; 027 028import org.ametys.cms.workflow.EditContentFunction; 029import org.ametys.plugins.repository.RepositoryConstants; 030import org.ametys.plugins.repository.jcr.NodeTypeHelper; 031 032/** 033 * Provides the following predicates: 034 * <ul> 035 * <li>propertyNamePredicate - accept a property depending on his name. 036 * <li>nodeNamePredicate - accept a node depending on his name. 037 * <li>nodeTypePredicate - accept a node depending on his node type. 038 * </ul> 039 */ 040public class AmetysPredicateUtils extends PredicateUtils 041{ 042 private static AllowedForLivePredicate _allowedLivePredicate = new AllowedForLivePredicate(); 043 044 /** 045 * Tests if the property has the following name. 046 * @param propertyName the property name. 047 * @return <code>true</code> if the property has the given name, 048 * <code>false</code> otherwise. 049 */ 050 public static Predicate propertyNamePredicate(final String propertyName) 051 { 052 return new Predicate() 053 { 054 @Override 055 public boolean evaluate(Object object) 056 { 057 if (object instanceof Property) 058 { 059 try 060 { 061 return ((Property) object).getName().equals(propertyName); 062 } 063 catch (RepositoryException e) 064 { 065 throw new RuntimeException("Unable to get property name", e); 066 } 067 } 068 069 return false; 070 } 071 }; 072 } 073 074 /** 075 * Tests if the property has a given name in a list. 076 * @param propertyNames one or several property names. 077 * @return <code>true</code> if the property has on of the given names, 078 * <code>false</code> otherwise. 079 */ 080 public static Predicate propertyNamesPredicate(final String ... propertyNames) 081 { 082 return new Predicate() 083 { 084 @Override 085 public boolean evaluate(Object object) 086 { 087 if (object instanceof Property) 088 { 089 try 090 { 091 String propName = ((Property) object).getName(); 092 return ArrayUtils.contains(propertyNames, propName); 093 } 094 catch (RepositoryException e) 095 { 096 throw new RuntimeException("Unable to get property name", e); 097 } 098 } 099 return false; 100 } 101 }; 102 } 103 104 /** 105 * Tests if the property is not a protected one (e.g. jcr:uuid). 106 * @param predicate the additional predicate to evaluate. 107 * @return <code>true</code> if the property has the given name, 108 * <code>false</code> otherwise. 109 */ 110 public static Predicate ignoreProtectedProperties(final Predicate predicate) 111 { 112 return new IgnoreProtectedPredicate(predicate); 113 } 114 115 /** 116 * Tests if the node has the following name. 117 * @param nodeName the node name. 118 * @return <code>true</code> if the node has the given name, 119 * <code>false</code> otherwise. 120 */ 121 public static Predicate nodeNamePredicate(final String nodeName) 122 { 123 return new Predicate() 124 { 125 @Override 126 public boolean evaluate(Object object) 127 { 128 if (object instanceof Node) 129 { 130 try 131 { 132 return ((Node) object).getName().equals(nodeName); 133 } 134 catch (RepositoryException e) 135 { 136 throw new RuntimeException("Unable to get node name", e); 137 } 138 } 139 140 return false; 141 } 142 }; 143 } 144 145 /** 146 * Tests if the node is of the given node type. 147 * @param nodeTypeName the node type name. 148 * @return <code>true</code> if the node has the given node type, 149 * <code>false</code> otherwise. 150 */ 151 public static Predicate nodeTypePredicate(final String nodeTypeName) 152 { 153 return new Predicate() 154 { 155 @Override 156 public boolean evaluate(Object object) 157 { 158 if (object instanceof Node) 159 { 160 try 161 { 162 return ((Node) object).isNodeType(nodeTypeName); 163 } 164 catch (RepositoryException e) 165 { 166 throw new RuntimeException("Unable to test node type", e); 167 } 168 } 169 170 return false; 171 } 172 }; 173 } 174 175 private static final class IgnoreProtectedPredicate implements Predicate 176 { 177 private Predicate _predicate; 178 179 IgnoreProtectedPredicate(Predicate predicate) 180 { 181 _predicate = predicate; 182 } 183 184 @Override 185 public boolean evaluate(Object object) 186 { 187 if (object instanceof Property) 188 { 189 Property property = (Property) object; 190 191 try 192 { 193 Node parentNode = property.getParent(); 194 String propertyName = property.getName(); 195 196 if (parentNode.isNodeType("nt:frozenNode")) 197 { 198 if (propertyName.startsWith("jcr:")) 199 { 200 if (!propertyName.equals("jcr:encoding") && !propertyName.equals("jcr:mimeType") 201 && !propertyName.equals("jcr:data") && !propertyName.equals("jcr:lastModified")) 202 { 203 // Refuse potential protected property 204 return false; 205 } 206 } 207 208 return _predicate.evaluate(object); 209 } 210 else 211 { 212 // If property is not protected, do process it 213 return !property.getDefinition().isProtected() && _predicate.evaluate(object); 214 } 215 } 216 catch (RepositoryException e) 217 { 218 throw new RuntimeException("Unable to process property", e); 219 } 220 } 221 222 return false; 223 } 224 } 225 226 /** 227 * Tests if the node or property is allowed in the live workspace 228 * @return <code>true</code> if the property or node is allowed, 229 * <code>false</code> otherwise. 230 */ 231 public static Predicate isAllowedForLiveContent() 232 { 233 return _allowedLivePredicate; 234 } 235 236 private static final class AllowedForLivePredicate implements Predicate 237 { 238 AllowedForLivePredicate() 239 { 240 } 241 242 @Override 243 public boolean evaluate(Object object) 244 { 245 if (object instanceof Property) 246 { 247 248 Property property = (Property) object; 249 try 250 { 251 // oswf:* item are not allowed 252 return !property.getName().startsWith("oswf:") 253 && !property.getName().equals(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":initial-content") 254 && !property.getName().equals(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":workflowRef") 255 && !(property.getName().startsWith(EditContentFunction.JCR_REFERENCE_PREFIX) && property.getType() == PropertyType.REFERENCE); 256 } 257 catch (RepositoryException e) 258 { 259 throw new RuntimeException("Unable to process property", e); 260 } 261 } 262 else if (object instanceof Node) 263 { 264 Node node = (Node) object; 265 try 266 { 267 String nodeType = NodeTypeHelper.getNodeTypeName(node); 268 269 // oswf:* item are not allowed 270 return !nodeType.startsWith("oswf:"); 271 } 272 catch (RepositoryException e) 273 { 274 throw new RuntimeException("Unable to process node", e); 275 } 276 } 277 278 return false; 279 } 280 } 281 282 283 /** 284 * Tests if the node or property is allowed in the live workspace 285 * @param node The parent node. 286 * @return <code>true</code> if the property or node is allowed, 287 * <code>false</code> otherwise. 288 */ 289 public static Predicate isNonVersionned(Node node) 290 { 291 return new NonVersionnedPredicate(node); 292 } 293 294 private static final class NonVersionnedPredicate implements Predicate 295 { 296 private Node _node; 297 298 NonVersionnedPredicate(Node node) 299 { 300 _node = node; 301 } 302 303 @Override 304 public boolean evaluate(Object object) 305 { 306 if (object instanceof Property) 307 { 308 Property property = (Property) object; 309 310 try 311 { 312 if (!property.getParent().getIdentifier().equals(_node.getIdentifier())) 313 { 314 // The property must be one of a child node (of a non versionned node) 315 return true; 316 } 317 return property.getDefinition().getOnParentVersion() == OnParentVersionAction.IGNORE; 318 } 319 catch (RepositoryException e) 320 { 321 throw new RuntimeException("Unable to process property", e); 322 } 323 } 324 else if (object instanceof Node) 325 { 326 Node node = (Node) object; 327 try 328 { 329 if (!node.getParent().getIdentifier().equals(_node.getIdentifier())) 330 { 331 // The node must be one of a child node (of a non versionned node) 332 return true; 333 } 334 return node.getDefinition().getOnParentVersion() == OnParentVersionAction.IGNORE; 335 } 336 catch (RepositoryException e) 337 { 338 throw new RuntimeException("Unable to process node", e); 339 } 340 } 341 342 return false; 343 } 344 } 345}