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.right.ProfileAssignmentStorage.AnonymousOrAnyConnectedKeys;
029import org.ametys.core.right.ProfileAssignmentStorage.UserOrGroup;
030import org.ametys.core.user.UserIdentity;
031import org.ametys.plugins.repository.AmetysObject;
032import org.ametys.plugins.repository.AmetysObjectIterable;
033import org.ametys.plugins.repository.AmetysRepositoryException;
034import org.ametys.plugins.repository.ModifiableACLAmetysObject;
035import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
036import org.ametys.plugins.repository.RepositoryIntegrityViolationException;
037import org.ametys.plugins.repository.UnknownAmetysObjectException;
038import org.ametys.plugins.repository.jcr.ACLJCRAmetysObjectHelper;
039import org.ametys.plugins.repository.jcr.NodeHelper;
040import org.ametys.plugins.repository.jcr.SimpleAmetysObject;
041
042/**
043 * An {@link AmetysObject} representing a collection of other {@link AmetysObject}s.<br>
044 * The collection stored its contents in the JCR Repository in a hash tree for
045 * optimizing performances.<br>
046 * Please note that this implementation does not keep the insertion order of elements.
047 * @param <F> the type of the actual factory.
048 * @param <A> the type of the composite {@link AmetysObject}.
049 */
050public class AmetysObjectCollection<F extends AmetysObjectCollectionFactory, A extends AmetysObject> extends SimpleAmetysObject<F> implements ModifiableTraversableAmetysObject, Iterable<A>, ModifiableACLAmetysObject
051{
052    AmetysObjectCollectionFactory _factory;
053    
054    /**
055     * Creates an {@link AmetysObjectCollection}.
056     * @param node the node backing this AmetysObject.
057     * @param parentPath the parentPath in the Ametys hierarchy.
058     * @param factory the {@link AmetysObjectCollectionFactory} which created the AmetysObject.
059     */
060    public AmetysObjectCollection(Node node, String parentPath, F factory)
061    {
062        super(node, parentPath, factory);
063        _factory = factory;
064    }
065
066    @SuppressWarnings("unchecked")
067    public AmetysObjectIterable<A> getChildren() throws AmetysRepositoryException
068    {
069        return _factory.getChildren(getPath(), getNode());
070    }
071    
072    public Iterator<A> iterator()
073    {
074        return _factory.getChildren(getPath(), getNode()).iterator();
075    }
076    
077    public boolean hasChild(String name) throws AmetysRepositoryException
078    {
079        if (name == null || "".equals(name) || name.charAt(0) == '/')
080        {
081            throw new AmetysRepositoryException("Child name cannot be null, empty or absolute");
082        }
083        
084        if (".".equals(name) || "..".equals(name))
085        {
086            throw new AmetysRepositoryException("Child name cannot be . or ..");
087        }
088        
089        try
090        {
091            return getNode().hasNode(NodeHelper.getFullHashPath(name));
092        }
093        catch (RepositoryException e)
094        {
095            throw new AmetysRepositoryException("An error occured getting child object " + name + " for object " + getName(), e);
096        }
097    }
098    
099    @SuppressWarnings("unchecked")
100    public A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
101    {
102        if (path == null || "".equals(path) || path.charAt(0) == '/')
103        {
104            throw new AmetysRepositoryException("Child path cannot be null, empty or absolute");
105        }
106        
107        String subPath = null;
108        String name;
109        
110        int i = path.indexOf('/');
111        if (i == -1)
112        {
113            name = path;
114        }
115        else
116        {
117            name = path.substring(0, i);
118            subPath = path.substring(i + 1);
119        }
120        
121        if (".".equals(name) || "..".equals(name))
122        {
123            throw new AmetysRepositoryException("Path cannot contain segment with . or ..");
124        }
125        
126        try
127        {
128            Node childNode = getNode().getNode(NodeHelper.getFullHashPath(name));
129            
130            return (A) _factory.getObject(null, childNode, subPath);
131        }
132        catch (PathNotFoundException e)
133        {
134            throw new UnknownAmetysObjectException("Unable to retrieve child node for path: " + path, e);
135        }
136        catch (RepositoryException e)
137        {
138            throw new AmetysRepositoryException(e);
139        }
140    }
141    
142    @SuppressWarnings("unchecked")
143    public A createChild(String name, String type) throws AmetysRepositoryException, RepositoryIntegrityViolationException
144    {
145        Node contextNode = NodeHelper.getOrCreateFinalHashNode(getNode(), name);
146        return (A) _factory.createChild(getPath(), contextNode, name, type);
147    }
148    
149    @Override
150    @SuppressWarnings("unchecked")
151    public AmetysObject getParent() throws AmetysRepositoryException
152    {
153        return _factory.getParent(this);
154    }
155    
156    public Map<AnonymousOrAnyConnectedKeys, Set<String>> getProfilesForAnonymousAndAnyConnectedUser()
157    {
158        return ACLJCRAmetysObjectHelper.getProfilesForAnonymousAndAnyConnectedUser(getNode());
159    }
160    
161    public Map<GroupIdentity, Map<UserOrGroup, Set<String>>> getProfilesForGroups(Set<GroupIdentity> groups)
162    {
163        return ACLJCRAmetysObjectHelper.getProfilesForGroups(getNode(), groups);
164    }
165    
166    public Map<UserIdentity, Map<UserOrGroup, Set<String>>> getProfilesForUsers(UserIdentity user)
167    {
168        return ACLJCRAmetysObjectHelper.getProfilesForUsers(getNode(), user);
169    }
170    
171    public void addAllowedProfilesForAnyConnectedUser(Set<String> profileIds)
172    {
173        ACLJCRAmetysObjectHelper.addAllowedProfilesForAnyConnectedUser(getNode(), profileIds);
174    }
175    
176    public void removeAllowedProfilesForAnyConnectedUser(Set<String> profileIds)
177    {
178        ACLJCRAmetysObjectHelper.removeAllowedProfilesForAnyConnectedUser(getNode(), profileIds);
179    }
180    
181    public void addDeniedProfilesForAnyConnectedUser(Set<String> profileIds)
182    {
183        ACLJCRAmetysObjectHelper.addDeniedProfilesForAnyConnectedUser(getNode(), profileIds);
184    }
185    
186    public void removeDeniedProfilesForAnyConnectedUser(Set<String> profileIds)
187    {
188        ACLJCRAmetysObjectHelper.removeDeniedProfilesForAnyConnectedUser(getNode(), profileIds);
189    }
190    
191    public void addAllowedProfilesForAnonymous(Set<String> profileIds)
192    {
193        ACLJCRAmetysObjectHelper.addAllowedProfilesForAnonymous(getNode(), profileIds);
194    }
195    
196    public void removeAllowedProfilesForAnonymous(Set<String> profileIds)
197    {
198        ACLJCRAmetysObjectHelper.removeAllowedProfilesForAnonymous(getNode(), profileIds);
199    }
200    
201    public void addDeniedProfilesForAnonymous(Set<String> profileIds)
202    {
203        ACLJCRAmetysObjectHelper.addDeniedProfilesForAnonymous(getNode(), profileIds);
204    }
205    
206    public void removeDeniedProfilesForAnonymous(Set<String> profileIds)
207    {
208        ACLJCRAmetysObjectHelper.removeDeniedProfilesForAnonymous(getNode(), profileIds);
209    }
210    
211    public void addAllowedUsers(Set<UserIdentity> users, String profileId)
212    {
213        ACLJCRAmetysObjectHelper.addAllowedUsers(users, getNode(), profileId);
214    }
215    
216    public void removeAllowedUsers(Set<UserIdentity> users, String profileId)
217    {
218        ACLJCRAmetysObjectHelper.removeAllowedUsers(users, getNode(), profileId);
219    }
220    
221    public void removeAllowedUsers(Set<UserIdentity> users)
222    {
223        ACLJCRAmetysObjectHelper.removeAllowedUsers(users, getNode());
224    }
225    
226    public void addAllowedGroups(Set<GroupIdentity> groups, String profileId)
227    {
228        ACLJCRAmetysObjectHelper.addAllowedGroups(groups, getNode(), profileId);
229    }
230    
231    public void removeAllowedGroups(Set<GroupIdentity> groups, String profileId)
232    {
233        ACLJCRAmetysObjectHelper.removeAllowedGroups(groups, getNode(), profileId);
234    }
235    
236    public void removeAllowedGroups(Set<GroupIdentity> groups)
237    {
238        ACLJCRAmetysObjectHelper.removeAllowedGroups(groups, getNode());
239    }
240    
241    public void addDeniedUsers(Set<UserIdentity> users, String profileId)
242    {
243        ACLJCRAmetysObjectHelper.addDeniedUsers(users, getNode(), profileId);
244    }
245    
246    public void removeDeniedUsers(Set<UserIdentity> users, String profileId)
247    {
248        ACLJCRAmetysObjectHelper.removeDeniedUsers(users, getNode(), profileId);
249    }
250    
251    public void removeDeniedUsers(Set<UserIdentity> users)
252    {
253        ACLJCRAmetysObjectHelper.removeDeniedUsers(users, getNode());
254    }
255    
256    public void addDeniedGroups(Set<GroupIdentity> groups, String profileId)
257    {
258        ACLJCRAmetysObjectHelper.addDeniedGroups(groups, getNode(), profileId);
259    }
260    
261    public void removeDeniedGroups(Set<GroupIdentity> groups, String profileId)
262    {
263        ACLJCRAmetysObjectHelper.removeDeniedGroups(groups, getNode(), profileId);
264    }
265    
266    public void removeDeniedGroups(Set<GroupIdentity> groups)
267    {
268        ACLJCRAmetysObjectHelper.removeDeniedGroups(groups, getNode());
269    }
270    
271    public boolean isInheritanceDisallowed()
272    {
273        return ACLJCRAmetysObjectHelper.isInheritanceDisallowed(getNode());
274    }
275    
276    public void disallowInheritance(boolean disallow)
277    {
278        ACLJCRAmetysObjectHelper.disallowInheritance(getNode(), disallow);
279    }
280}