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.Item; 019import javax.jcr.Node; 020import javax.jcr.Property; 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.plugins.repository.RepositoryConstants; 029import org.ametys.plugins.repository.jcr.NodeTypeHelper; 030 031/** 032 * Provides the following predicates: 033 * <ul> 034 * <li>propertyNamePredicate - accept a property depending on his name. 035 * <li>nodeNamePredicate - accept a node depending on his name. 036 * <li>nodeTypePredicate - accept a node depending on his node type. 037 * </ul> 038 */ 039public class AmetysPredicateUtils extends PredicateUtils 040{ 041 private static AllowedForLivePredicate _allowedLivePredicate = new AllowedForLivePredicate(); 042 043 /** 044 * Tests if the property has the following name. 045 * @param propertyName the property name. 046 * @return <code>true</code> if the property has the given name, 047 * <code>false</code> otherwise. 048 */ 049 public static Predicate propertyNamePredicate(final String propertyName) 050 { 051 return new Predicate() 052 { 053 @Override 054 public boolean evaluate(Object object) 055 { 056 if (object instanceof Property) 057 { 058 try 059 { 060 return ((Property) object).getName().equals(propertyName); 061 } 062 catch (RepositoryException e) 063 { 064 throw new RuntimeException("Unable to get property name", e); 065 } 066 } 067 068 return false; 069 } 070 }; 071 } 072 073 /** 074 * Tests if the property has a given name in a list. 075 * @param propertyNames one or several property names. 076 * @return <code>true</code> if the property has on of the given names, 077 * <code>false</code> otherwise. 078 */ 079 public static Predicate propertyNamesPredicate(final String ... propertyNames) 080 { 081 return new Predicate() 082 { 083 @Override 084 public boolean evaluate(Object object) 085 { 086 if (object instanceof Property) 087 { 088 try 089 { 090 String propName = ((Property) object).getName(); 091 return ArrayUtils.contains(propertyNames, propName); 092 } 093 catch (RepositoryException e) 094 { 095 throw new RuntimeException("Unable to get property name", e); 096 } 097 } 098 return false; 099 } 100 }; 101 } 102 103 /** 104 * Tests if the property is not a protected one (e.g. jcr:uuid). 105 * @param predicate the additional predicate to evaluate. 106 * @return <code>true</code> if the property has the given name, 107 * <code>false</code> otherwise. 108 */ 109 public static Predicate ignoreProtectedProperties(final Predicate predicate) 110 { 111 return new IgnoreProtectedPredicate(predicate); 112 } 113 114 /** 115 * Tests if the node has the following name. 116 * @param nodeName the node name. 117 * @return <code>true</code> if the node has the given name, 118 * <code>false</code> otherwise. 119 */ 120 public static Predicate nodeNamePredicate(final String nodeName) 121 { 122 return new Predicate() 123 { 124 @Override 125 public boolean evaluate(Object object) 126 { 127 if (object instanceof Node) 128 { 129 try 130 { 131 return ((Node) object).getName().equals(nodeName); 132 } 133 catch (RepositoryException e) 134 { 135 throw new RuntimeException("Unable to get node name", e); 136 } 137 } 138 139 return false; 140 } 141 }; 142 } 143 144 /** 145 * Tests if the node or property is a Ametys attribute, ie. it is prefixed by 'ametys:' 146 * @return <code>true</code> if the name starts with 'ametys:' 147 * <code>false</code> otherwise. 148 */ 149 public static Predicate ametysAttributePredicate() 150 { 151 return new Predicate() 152 { 153 @Override 154 public boolean evaluate(Object object) 155 { 156 if (object instanceof Item) 157 { 158 try 159 { 160 return ((Item) object).getName().startsWith(RepositoryConstants.NAMESPACE_PREFIX + ":"); 161 } 162 catch (RepositoryException e) 163 { 164 throw new RuntimeException("Unable to get item name", e); 165 } 166 } 167 168 return false; 169 } 170 }; 171 } 172 173 /** 174 * Tests if the node is of the given node type. 175 * @param nodeTypeName the node type name. 176 * @return <code>true</code> if the node has the given node type, 177 * <code>false</code> otherwise. 178 */ 179 public static Predicate nodeTypePredicate(final String nodeTypeName) 180 { 181 return new Predicate() 182 { 183 @Override 184 public boolean evaluate(Object object) 185 { 186 if (object instanceof Node) 187 { 188 try 189 { 190 return ((Node) object).isNodeType(nodeTypeName); 191 } 192 catch (RepositoryException e) 193 { 194 throw new RuntimeException("Unable to test node type", e); 195 } 196 } 197 198 return false; 199 } 200 }; 201 } 202 203 private static final class IgnoreProtectedPredicate implements Predicate 204 { 205 private Predicate _predicate; 206 207 IgnoreProtectedPredicate(Predicate predicate) 208 { 209 _predicate = predicate; 210 } 211 212 @Override 213 public boolean evaluate(Object object) 214 { 215 if (object instanceof Property) 216 { 217 Property property = (Property) object; 218 219 try 220 { 221 Node parentNode = property.getParent(); 222 String propertyName = property.getName(); 223 224 if (parentNode.isNodeType("nt:frozenNode")) 225 { 226 if (propertyName.startsWith("jcr:")) 227 { 228 if (!propertyName.equals("jcr:encoding") && !propertyName.equals("jcr:mimeType") 229 && !propertyName.equals("jcr:data") && !propertyName.equals("jcr:lastModified")) 230 { 231 // Refuse potential protected property 232 return false; 233 } 234 } 235 236 return _predicate.evaluate(object); 237 } 238 else 239 { 240 // If property is not protected, do process it 241 return !property.getDefinition().isProtected() && _predicate.evaluate(object); 242 } 243 } 244 catch (RepositoryException e) 245 { 246 throw new RuntimeException("Unable to process property", e); 247 } 248 } 249 250 return false; 251 } 252 } 253 254 /** 255 * Tests if the node or property is allowed in the live workspace 256 * @return <code>true</code> if the property or node is allowed, 257 * <code>false</code> otherwise. 258 */ 259 public static Predicate isAllowedForLiveContent() 260 { 261 return _allowedLivePredicate; 262 } 263 264 private static final class AllowedForLivePredicate implements Predicate 265 { 266 AllowedForLivePredicate() 267 { 268 } 269 270 @Override 271 public boolean evaluate(Object object) 272 { 273 if (object instanceof Property) 274 { 275 276 Property property = (Property) object; 277 try 278 { 279 // oswf:* item are not allowed 280 return !property.getName().startsWith("oswf:") 281 && !property.getName().equals(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":initial-content") 282 && !property.getName().equals(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":workflowRef"); 283 } 284 catch (RepositoryException e) 285 { 286 throw new RuntimeException("Unable to process property", e); 287 } 288 } 289 else if (object instanceof Node) 290 { 291 Node node = (Node) object; 292 try 293 { 294 String nodeType = NodeTypeHelper.getNodeTypeName(node); 295 296 // oswf:* item are not allowed 297 return !nodeType.startsWith("oswf:"); 298 } 299 catch (RepositoryException e) 300 { 301 throw new RuntimeException("Unable to process node", e); 302 } 303 } 304 305 return false; 306 } 307 } 308 309 310 /** 311 * Tests if the node or property is allowed in the live workspace 312 * @param node The parent node. 313 * @return <code>true</code> if the property or node is allowed, 314 * <code>false</code> otherwise. 315 */ 316 public static Predicate isNonVersionned(Node node) 317 { 318 return new NonVersionnedPredicate(node); 319 } 320 321 private static final class NonVersionnedPredicate implements Predicate 322 { 323 private Node _node; 324 325 NonVersionnedPredicate(Node node) 326 { 327 _node = node; 328 } 329 330 @Override 331 public boolean evaluate(Object object) 332 { 333 if (object instanceof Property) 334 { 335 Property property = (Property) object; 336 337 try 338 { 339 if (!property.getParent().getIdentifier().equals(_node.getIdentifier())) 340 { 341 // The property must be one of a child node (of a non versionned node) 342 return true; 343 } 344 return property.getDefinition().getOnParentVersion() == OnParentVersionAction.IGNORE; 345 } 346 catch (RepositoryException e) 347 { 348 throw new RuntimeException("Unable to process property", e); 349 } 350 } 351 else if (object instanceof Node) 352 { 353 Node node = (Node) object; 354 try 355 { 356 if (!node.getParent().getIdentifier().equals(_node.getIdentifier())) 357 { 358 // The node must be one of a child node (of a non versionned node) 359 return true; 360 } 361 return node.getDefinition().getOnParentVersion() == OnParentVersionAction.IGNORE; 362 } 363 catch (RepositoryException e) 364 { 365 throw new RuntimeException("Unable to process node", e); 366 } 367 } 368 369 return false; 370 } 371 } 372}