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 */ 016 017package org.ametys.plugins.repository.collection; 018 019import java.util.Iterator; 020import java.util.Map; 021import java.util.Set; 022 023import javax.jcr.Node; 024import javax.jcr.PathNotFoundException; 025import javax.jcr.RepositoryException; 026 027import org.ametys.core.group.GroupIdentity; 028import org.ametys.core.user.UserIdentity; 029import org.ametys.plugins.repository.AmetysObject; 030import org.ametys.plugins.repository.AmetysObjectIterable; 031import org.ametys.plugins.repository.AmetysRepositoryException; 032import org.ametys.plugins.repository.ModifiableACLAmetysObject; 033import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 034import org.ametys.plugins.repository.RepositoryIntegrityViolationException; 035import org.ametys.plugins.repository.UnknownAmetysObjectException; 036import org.ametys.plugins.repository.jcr.ACLJCRAmetysObjectHelper; 037import org.ametys.plugins.repository.jcr.SimpleAmetysObject; 038 039/** 040 * An {@link AmetysObject} representing a collection of other {@link AmetysObject}s.<br> 041 * The collection stored its contents in the JCR Repository in a hash tree for 042 * optimizing performances.<br> 043 * Please note that this implementation does not keep the insertion order of elements. 044 * @param <F> the type of the actual factory. 045 * @param <A> the type of the composite {@link AmetysObject}. 046 */ 047public class AmetysObjectCollection<F extends AmetysObjectCollectionFactory, A extends AmetysObject> extends SimpleAmetysObject<F> implements ModifiableTraversableAmetysObject, Iterable<A>, ModifiableACLAmetysObject 048{ 049 AmetysObjectCollectionFactory _factory; 050 051 /** 052 * Creates an {@link AmetysObjectCollection}. 053 * @param node the node backing this AmetysObject. 054 * @param parentPath the parentPath in the Ametys hierarchy. 055 * @param factory the {@link AmetysObjectCollectionFactory} which created the AmetysObject. 056 */ 057 public AmetysObjectCollection(Node node, String parentPath, F factory) 058 { 059 super(node, parentPath, factory); 060 _factory = factory; 061 } 062 063 @SuppressWarnings("unchecked") 064 public AmetysObjectIterable<A> getChildren() throws AmetysRepositoryException 065 { 066 return _factory.getChildren(getPath(), getNode()); 067 } 068 069 public Iterator<A> iterator() 070 { 071 return _factory.getChildren(getPath(), getNode()).iterator(); 072 } 073 074 public boolean hasChild(String name) throws AmetysRepositoryException 075 { 076 if (name == null || "".equals(name) || name.charAt(0) == '/') 077 { 078 throw new AmetysRepositoryException("Child name cannot be null, empty or absolute"); 079 } 080 081 if (".".equals(name) || "..".equals(name)) 082 { 083 throw new AmetysRepositoryException("Child name cannot be . or .."); 084 } 085 086 try 087 { 088 return getNode().hasNode(_getPath(name)); 089 } 090 catch (RepositoryException e) 091 { 092 throw new AmetysRepositoryException("An error occured getting child object " + name + " for object " + getName(), e); 093 } 094 } 095 096 @SuppressWarnings("unchecked") 097 public A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException 098 { 099 if (path == null || "".equals(path) || path.charAt(0) == '/') 100 { 101 throw new AmetysRepositoryException("Child path cannot be null, empty or absolute"); 102 } 103 104 String subPath = null; 105 String name; 106 107 int i = path.indexOf('/'); 108 if (i == -1) 109 { 110 name = path; 111 } 112 else 113 { 114 name = path.substring(0, i); 115 subPath = path.substring(i + 1); 116 } 117 118 if (".".equals(name) || "..".equals(name)) 119 { 120 throw new AmetysRepositoryException("Path cannot contain segment with . or .."); 121 } 122 123 try 124 { 125 Node childNode = getNode().getNode(_getPath(name)); 126 127 return (A) _factory.getObject(null, childNode, subPath); 128 } 129 catch (PathNotFoundException e) 130 { 131 throw new UnknownAmetysObjectException("Unable to retrieve child node for path: " + path, e); 132 } 133 catch (RepositoryException e) 134 { 135 throw new AmetysRepositoryException(e); 136 } 137 } 138 139 @SuppressWarnings("unchecked") 140 public A createChild(String name, String type) throws AmetysRepositoryException, RepositoryIntegrityViolationException 141 { 142 String[] hash = _factory.getHashedPath(name); 143 144 Node contextNode = getNode(); 145 146 try 147 { 148 for (String hashPart : hash) 149 { 150 if (!contextNode.hasNode(hashPart)) 151 { 152 contextNode = contextNode.addNode(hashPart, AmetysObjectCollectionFactory.COLLECTION_ELEMENT_NODETYPE); 153 } 154 else 155 { 156 contextNode = contextNode.getNode(hashPart); 157 } 158 } 159 160 return (A) _factory.createChild(getPath(), contextNode, name, type); 161 } 162 catch (RepositoryException e) 163 { 164 throw new AmetysRepositoryException("Unable to create child: " + name + " and type: " + type, e); 165 } 166 } 167 168 @Override 169 @SuppressWarnings("unchecked") 170 public AmetysObject getParent() throws AmetysRepositoryException 171 { 172 return _factory.getParent(this); 173 } 174 175 private String _getPath(String childName) 176 { 177 String[] hash = _factory.getHashedPath(childName); 178 179 StringBuilder path = new StringBuilder(); 180 181 for (String hashPart : hash) 182 { 183 path.append(hashPart); 184 path.append('/'); 185 } 186 187 path.append(childName); 188 189 return path.toString(); 190 } 191 192 @Override 193 public Set<String> getAllowedProfilesForAnyConnectedUser() 194 { 195 return ACLJCRAmetysObjectHelper.getAllowedProfilesForAnyConnectedUser(getNode()); 196 } 197 198 @Override 199 public void addAllowedProfilesForAnyConnectedUser(Set<String> profileIds) 200 { 201 ACLJCRAmetysObjectHelper.addAllowedProfilesForAnyConnectedUser(getNode(), profileIds); 202 } 203 204 @Override 205 public void removeAllowedProfilesForAnyConnectedUser(Set<String> profileIds) 206 { 207 ACLJCRAmetysObjectHelper.removeAllowedProfilesForAnyConnectedUser(getNode(), profileIds); 208 } 209 210 @Override 211 public Set<String> getDeniedProfilesForAnyConnectedUser() 212 { 213 return ACLJCRAmetysObjectHelper.getDeniedProfilesForAnyConnectedUser(getNode()); 214 } 215 216 @Override 217 public void addDeniedProfilesForAnyConnectedUser(Set<String> profileIds) 218 { 219 ACLJCRAmetysObjectHelper.addDeniedProfilesForAnyConnectedUser(getNode(), profileIds); 220 } 221 222 @Override 223 public void removeDeniedProfilesForAnyConnectedUser(Set<String> profileIds) 224 { 225 ACLJCRAmetysObjectHelper.removeDeniedProfilesForAnyConnectedUser(getNode(), profileIds); 226 } 227 228 @Override 229 public Set<String> getAllowedProfilesForAnonymous() 230 { 231 return ACLJCRAmetysObjectHelper.getAllowedProfilesForAnonymous(getNode()); 232 } 233 234 @Override 235 public void addAllowedProfilesForAnonymous(Set<String> profileIds) 236 { 237 ACLJCRAmetysObjectHelper.addAllowedProfilesForAnonymous(getNode(), profileIds); 238 } 239 240 @Override 241 public void removeAllowedProfilesForAnonymous(Set<String> profileIds) 242 { 243 ACLJCRAmetysObjectHelper.removeAllowedProfilesForAnonymous(getNode(), profileIds); 244 } 245 246 @Override 247 public Set<String> getDeniedProfilesForAnonymous() 248 { 249 return ACLJCRAmetysObjectHelper.getDeniedProfilesForAnonymous(getNode()); 250 } 251 252 @Override 253 public void addDeniedProfilesForAnonymous(Set<String> profileIds) 254 { 255 ACLJCRAmetysObjectHelper.addDeniedProfilesForAnonymous(getNode(), profileIds); 256 } 257 258 @Override 259 public void removeDeniedProfilesForAnonymous(Set<String> profileIds) 260 { 261 ACLJCRAmetysObjectHelper.removeDeniedProfilesForAnonymous(getNode(), profileIds); 262 } 263 264 @Override 265 public Set<String> getAllowedProfilesForUser(UserIdentity user) 266 { 267 return ACLJCRAmetysObjectHelper.getAllowedProfilesForUser(getNode(), user); 268 } 269 270 @Override 271 public Map<UserIdentity, Set<String>> getAllowedProfilesForUsers() 272 { 273 return ACLJCRAmetysObjectHelper.getAllowedProfilesForUsers(getNode()); 274 } 275 276 @Override 277 public Set<UserIdentity> getAllowedUsers(String profileId) 278 { 279 return ACLJCRAmetysObjectHelper.getAllowedUsers(getNode(), profileId); 280 } 281 282 @Override 283 public void addAllowedUsers(Set<UserIdentity> users, String profileId) 284 { 285 ACLJCRAmetysObjectHelper.addAllowedUsers(users, getNode(), profileId); 286 } 287 288 @Override 289 public void removeAllowedUsers(Set<UserIdentity> users, String profileId) 290 { 291 ACLJCRAmetysObjectHelper.removeAllowedUsers(users, getNode(), profileId); 292 } 293 294 @Override 295 public void removeAllowedUsers(Set<UserIdentity> users) 296 { 297 ACLJCRAmetysObjectHelper.removeAllowedUsers(users, getNode()); 298 } 299 300 @Override 301 public Map<GroupIdentity, Set<String>> getAllowedProfilesForGroups() 302 { 303 return ACLJCRAmetysObjectHelper.getAllowedProfilesForGroups(getNode()); 304 } 305 306 @Override 307 public Set<GroupIdentity> getAllowedGroups(String profileId) 308 { 309 return ACLJCRAmetysObjectHelper.getAllowedGroups(getNode(), profileId); 310 } 311 312 @Override 313 public void addAllowedGroups(Set<GroupIdentity> groups, String profileId) 314 { 315 ACLJCRAmetysObjectHelper.addAllowedGroups(groups, getNode(), profileId); 316 } 317 318 @Override 319 public void removeAllowedGroups(Set<GroupIdentity> groups, String profileId) 320 { 321 ACLJCRAmetysObjectHelper.removeAllowedGroups(groups, getNode(), profileId); 322 } 323 324 @Override 325 public void removeAllowedGroups(Set<GroupIdentity> groups) 326 { 327 ACLJCRAmetysObjectHelper.removeAllowedGroups(groups, getNode()); 328 } 329 330 @Override 331 public Set<String> getDeniedProfilesForUser(UserIdentity user) 332 { 333 return ACLJCRAmetysObjectHelper.getDeniedProfilesForUser(getNode(), user); 334 } 335 336 @Override 337 public Map<UserIdentity, Set<String>> getDeniedProfilesForUsers() 338 { 339 return ACLJCRAmetysObjectHelper.getDeniedProfilesForUsers(getNode()); 340 } 341 342 @Override 343 public Set<UserIdentity> getDeniedUsers(String profileId) 344 { 345 return ACLJCRAmetysObjectHelper.getDeniedUsers(getNode(), profileId); 346 } 347 348 @Override 349 public void addDeniedUsers(Set<UserIdentity> users, String profileId) 350 { 351 ACLJCRAmetysObjectHelper.addDeniedUsers(users, getNode(), profileId); 352 } 353 354 @Override 355 public void removeDeniedUsers(Set<UserIdentity> users, String profileId) 356 { 357 ACLJCRAmetysObjectHelper.removeDeniedUsers(users, getNode(), profileId); 358 } 359 360 @Override 361 public void removeDeniedUsers(Set<UserIdentity> users) 362 { 363 ACLJCRAmetysObjectHelper.removeDeniedUsers(users, getNode()); 364 } 365 366 @Override 367 public Map<GroupIdentity, Set<String>> getDeniedProfilesForGroups() 368 { 369 return ACLJCRAmetysObjectHelper.getDeniedProfilesForGroups(getNode()); 370 } 371 372 @Override 373 public Set<GroupIdentity> getDeniedGroups(String profileId) 374 { 375 return ACLJCRAmetysObjectHelper.getDeniedGroups(getNode(), profileId); 376 } 377 378 @Override 379 public void addDeniedGroups(Set<GroupIdentity> groups, String profileId) 380 { 381 ACLJCRAmetysObjectHelper.addDeniedGroups(groups, getNode(), profileId); 382 } 383 384 @Override 385 public void removeDeniedGroups(Set<GroupIdentity> groups, String profileId) 386 { 387 ACLJCRAmetysObjectHelper.removeDeniedGroups(groups, getNode(), profileId); 388 } 389 390 @Override 391 public void removeDeniedGroups(Set<GroupIdentity> groups) 392 { 393 ACLJCRAmetysObjectHelper.removeDeniedGroups(groups, getNode()); 394 } 395}