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