001/*
002 *  Copyright 2016 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.plugins.userdirectory.page;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.Locale;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.commons.lang.StringUtils;
025
026import org.ametys.cms.repository.Content;
027import org.ametys.core.group.GroupIdentity;
028import org.ametys.core.right.ProfileAssignmentStorage.AnonymousOrAnyConnectedKeys;
029import org.ametys.core.right.ProfileAssignmentStorage.UserOrGroup;
030import org.ametys.core.right.RightManager;
031import org.ametys.core.user.UserIdentity;
032import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection;
033import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionDAO;
034import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionHelper;
035import org.ametys.plugins.explorer.resources.ResourceCollection;
036import org.ametys.plugins.repository.ACLAmetysObject;
037import org.ametys.plugins.repository.AmetysObject;
038import org.ametys.plugins.repository.AmetysObjectIterable;
039import org.ametys.plugins.repository.AmetysObjectResolver;
040import org.ametys.plugins.repository.AmetysRepositoryException;
041import org.ametys.plugins.repository.CollectionIterable;
042import org.ametys.plugins.repository.UnknownAmetysObjectException;
043import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
044import org.ametys.plugins.repository.data.holder.ModelLessDataHolder;
045import org.ametys.plugins.repository.data.holder.impl.DefaultModelLessDataHolder;
046import org.ametys.plugins.repository.data.repositorydata.RepositoryData;
047import org.ametys.plugins.repository.data.repositorydata.impl.MemoryRepositoryData;
048import org.ametys.plugins.userdirectory.UserDirectoryPageHandler;
049import org.ametys.web.data.type.ModelItemTypeExtensionPoint;
050import org.ametys.web.repository.page.Page;
051import org.ametys.web.repository.page.UnknownZoneException;
052import org.ametys.web.repository.page.Zone;
053import org.ametys.web.repository.site.Site;
054import org.ametys.web.repository.sitemap.Sitemap;
055import org.ametys.web.service.ServiceExtensionPoint;
056import org.ametys.web.skin.Skin;
057import org.ametys.web.skin.SkinsManager;
058
059/**
060 * Page representing a second-level page.
061 */
062public class UserPage implements Page, ACLAmetysObject
063{
064    private static final String __USER_PAGE_TEMPLATE = "user-page";
065    
066    private Page _root;
067    private int _initialDepth;
068    private String _title;
069    private AmetysObjectResolver _resolver;
070    private UserDirectoryPageHandler _userDirectoryPageHandler;
071    private SynchronizableContentsCollectionDAO _syncContentsCollectionDAO;
072    private SkinsManager _skinsManager;
073    private String _path;
074    private Content _syncContent;
075    private SynchronizableContentsCollectionHelper _sccHelper;
076
077    private ModelItemTypeExtensionPoint _pageDataTypeExtensionPoint;
078    private ModelItemTypeExtensionPoint _zoneDataTypeExtensionPoint;
079    private ServiceExtensionPoint _serviceExtensionPoint;
080    private ModelItemTypeExtensionPoint _zoneItemDataTypeExtensionPoint;
081    
082    /**
083     * Constructor.
084     * @param root the root page.
085     * @param syncContent the synchronized content
086     * @param path the path
087     * @param resolver the {@link AmetysObjectResolver}.
088     * @param userDirectoryPageHandler the user directory page handler
089     * @param syncContentsCollectionDAO The DAO for synchronizable collections
090     * @param skinsManager the skins manager
091     * @param sccHelper the SCC helper
092     * @param pageDataTypeExtensionPoint the extension point with available data types for pages
093     * @param zoneDataTypeExtensionPoint the extension point with available data types for zones
094     * @param serviceExtensionPoint the service extension point
095     * @param zoneItemDataTypeExtensionPoint the extension point with available data types for zone items
096     */
097    public UserPage(Page root, Content syncContent, String path, AmetysObjectResolver resolver, UserDirectoryPageHandler userDirectoryPageHandler, SynchronizableContentsCollectionDAO syncContentsCollectionDAO, SkinsManager skinsManager, SynchronizableContentsCollectionHelper sccHelper, ModelItemTypeExtensionPoint pageDataTypeExtensionPoint, ModelItemTypeExtensionPoint zoneDataTypeExtensionPoint, ServiceExtensionPoint serviceExtensionPoint, ModelItemTypeExtensionPoint zoneItemDataTypeExtensionPoint)
098    {
099        _root = root;
100        _path = path;
101        _resolver = resolver;
102        _userDirectoryPageHandler = userDirectoryPageHandler;
103        _syncContentsCollectionDAO = syncContentsCollectionDAO;
104        _skinsManager = skinsManager;
105        _syncContent = syncContent;
106        _sccHelper = sccHelper;
107        
108        _title = _syncContent.getTitle(new Locale(root.getSitemapName()));
109        _initialDepth = _userDirectoryPageHandler.getDepth(_root);
110
111        _pageDataTypeExtensionPoint = pageDataTypeExtensionPoint;
112        _zoneDataTypeExtensionPoint = zoneDataTypeExtensionPoint;
113        _serviceExtensionPoint = serviceExtensionPoint;
114        _zoneItemDataTypeExtensionPoint = zoneItemDataTypeExtensionPoint;
115    }
116
117    /**
118     * Compute a page id
119     * @param path The path
120     * @param rootId The root page id
121     * @param contentId The content id
122     * @return The id
123     */
124    public static String getId(String path, String rootId, String contentId)
125    {
126        // E.g: uduser://path?rootId=...&contentId=...
127        return "uduser://" + (StringUtils.isEmpty(path) ? "_root" : path) + "?rootId=" + rootId + "&contentId=" + contentId;
128    }
129    
130    /**
131     * Returns the associated synchronizable {@link Content}.
132     * @return the associated synchronizable {@link Content}.
133     */
134    public Content getSyncContent()
135    {
136        return _syncContent;
137    }
138    
139    
140    public int getDepth() throws AmetysRepositoryException
141    {
142        return _root.getDepth() + _initialDepth + 1;
143    }
144
145    
146    public Set<String> getReferers() throws AmetysRepositoryException
147    {
148        return null;
149    }
150
151    
152    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
153    {
154        return null;
155    }
156
157    
158    public String getTemplate() throws AmetysRepositoryException
159    {
160        Skin skin = _skinsManager.getSkin(getSite().getSkinId());
161        
162        if (skin.getTemplate(__USER_PAGE_TEMPLATE) != null)
163        {
164            return __USER_PAGE_TEMPLATE;
165        }
166        
167        return "page"; 
168    }
169
170    
171    public String getTitle() throws AmetysRepositoryException
172    {
173        return _title;
174    }
175    
176    
177    public String getLongTitle() throws AmetysRepositoryException
178    {
179        return _title;
180    }
181
182    
183    public PageType getType() throws AmetysRepositoryException
184    {
185        return PageType.CONTAINER;
186    }
187
188    
189    public String getURL() throws AmetysRepositoryException
190    {
191        throw new UnsupportedOperationException("#getURL is not supported on virtual user pages");
192    }
193
194    
195    public LinkType getURLType() throws AmetysRepositoryException
196    {
197        throw new UnsupportedOperationException("#getURLType is not supported on virtual user pages");
198    }
199
200    
201    public Zone getZone(String name) throws UnknownZoneException, AmetysRepositoryException
202    {
203        if (!"default".equals(name))
204        {
205            throw new IllegalArgumentException("Only the zone named 'default' is actually supported on virtual user pages.");
206        }
207        
208        return new UserZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint);
209    }
210
211    
212    public AmetysObjectIterable< ? extends Zone> getZones() throws AmetysRepositoryException
213    {
214        ArrayList<Zone> zones = new ArrayList<>();
215        zones.add(new UserZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint));
216        return new CollectionIterable<>(zones);
217    }
218
219    
220    public boolean hasZone(String name) throws AmetysRepositoryException
221    {
222        return "default".equals(name);
223    }
224
225    
226    public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException
227    {
228        ArrayList<Page> children = new ArrayList<>();
229        return new CollectionIterable<>(children);
230    }
231
232    
233    public String getPathInSitemap() throws AmetysRepositoryException
234    {
235        if (_path.equals("_root"))
236        {
237            return _root.getPathInSitemap() + "/" + getName();
238        }
239        else
240        {
241            String path = StringUtils.lowerCase(_path);
242            return _root.getPathInSitemap() + "/" + path + "/" + getName();
243        }
244    }
245
246    
247    public Site getSite() throws AmetysRepositoryException
248    {
249        return _root.getSite();
250    }
251
252    
253    public String getSiteName() throws AmetysRepositoryException
254    {
255        return _root.getSiteName();
256    }
257
258    
259    public Sitemap getSitemap() throws AmetysRepositoryException
260    {
261        return _root.getSitemap();
262    }
263
264    
265    public String getSitemapName() throws AmetysRepositoryException
266    {
267        return _root.getSitemapName();
268    }
269
270    
271    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
272    {
273        if (path.isEmpty())
274        {
275            throw new AmetysRepositoryException("path must be non empty");
276        }
277        
278        return null;
279    }
280
281    @SuppressWarnings("unchecked")
282    
283    public AmetysObjectIterable<? extends AmetysObject> getChildren() throws AmetysRepositoryException
284    {
285        return getChildrenPages();
286    }
287
288    
289    public boolean hasChild(String name) throws AmetysRepositoryException
290    {
291        return false;
292    }
293    
294    
295    public String getId() throws AmetysRepositoryException
296    {
297        return getId(_path, _root.getId(), _syncContent.getId());
298    }
299
300    
301    public String getName() throws AmetysRepositoryException
302    {
303        return _syncContent.getName();
304    }
305    
306    @SuppressWarnings("unchecked")
307    
308    public Page getParent() throws AmetysRepositoryException
309    {
310        if (_initialDepth > 0)
311        {
312            String pathName = StringUtils.substringAfterLast(_path, "/");
313            String name = _userDirectoryPageHandler.getName(pathName);
314            return new TransitionalPage(_root, name, _path, _resolver, _userDirectoryPageHandler, _syncContentsCollectionDAO, _skinsManager, _sccHelper, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint);
315        }
316        else
317        {
318            return _root;
319        }
320    }
321
322    
323    public String getParentPath() throws AmetysRepositoryException
324    {
325        if (_initialDepth > 0)
326        {
327            String path = StringUtils.lowerCase(_path);
328            return _root.getPath() + "/" + path;
329        }
330        else
331        {
332            return _root.getPath();
333        }
334    }
335
336    
337    public String getPath() throws AmetysRepositoryException
338    {
339        return getParentPath() + "/" + getName();
340    }
341
342    public ModelLessDataHolder getDataHolder()
343    {
344        RepositoryData repositoryData = new MemoryRepositoryData(getName());
345        return new DefaultModelLessDataHolder(_pageDataTypeExtensionPoint, repositoryData);
346    }
347
348    
349    public Set<String> getTags() throws AmetysRepositoryException
350    {
351        return Collections.emptySet();
352    }
353
354    
355    public AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePage) throws AmetysRepositoryException
356    {
357        ArrayList<Page> children = new ArrayList<>();
358        return new CollectionIterable<>(children);
359    }
360
361    
362    public boolean isVisible() throws AmetysRepositoryException
363    {
364        return false;
365    }
366
367    
368    public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException
369    {
370        throw new UnknownAmetysObjectException("There is no child for user page");
371    }
372
373    public Map<AnonymousOrAnyConnectedKeys, Set<String>> getProfilesForAnonymousAndAnyConnectedUser()
374    {
375        Set<String> collectionIds = _sccHelper.getSynchronizableCollectionIds(_syncContent);
376        for (String collectionId : collectionIds)
377        {
378            SynchronizableContentsCollection collection = _syncContentsCollectionDAO.getSynchronizableContentsCollection(collectionId);
379            if (collection != null)
380            {
381                String restrictedField = collection.getRestrictedField();
382                if (!StringUtils.isEmpty(restrictedField))
383                {
384                    Boolean restricted = _syncContent.getValue(restrictedField);
385                    if (restricted != null && restricted.booleanValue())
386                    {
387                        return Map.of(AnonymousOrAnyConnectedKeys.ANONYMOUS_DENIED, Set.of(RightManager.READER_PROFILE_ID));
388                    }
389                }
390            }
391        }
392        
393        return Map.of();
394    }
395    
396    public Map<GroupIdentity, Map<UserOrGroup, Set<String>>> getProfilesForGroups(Set<GroupIdentity> groups)
397    {
398        return Map.of();
399    }
400    
401    public Map<UserIdentity, Map<UserOrGroup, Set<String>>> getProfilesForUsers(UserIdentity user)
402    {
403        return Map.of();
404    }
405    
406    public boolean isInheritanceDisallowed()
407    {
408        return false;
409    }
410    
411    public ModelAwareDataHolder getTemplateParametersHolder() throws AmetysRepositoryException
412    {
413        return null;
414    }
415}