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.plugins.explorer.resources.ResourceCollection;
026import org.ametys.plugins.repository.AmetysObject;
027import org.ametys.plugins.repository.AmetysObjectIterable;
028import org.ametys.plugins.repository.AmetysObjectResolver;
029import org.ametys.plugins.repository.AmetysRepositoryException;
030import org.ametys.plugins.repository.CollectionIterable;
031import org.ametys.plugins.repository.UnknownAmetysObjectException;
032import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
033import org.ametys.plugins.repository.data.holder.ModelLessDataHolder;
034import org.ametys.plugins.repository.data.holder.impl.DefaultModelLessDataHolder;
035import org.ametys.plugins.repository.data.repositorydata.RepositoryData;
036import org.ametys.plugins.repository.data.repositorydata.impl.MemoryRepositoryData;
037import org.ametys.plugins.repository.data.type.RepositoryModelItemType;
038import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint;
039import org.ametys.web.repository.page.Page;
040import org.ametys.web.repository.page.UnknownZoneException;
041import org.ametys.web.repository.page.Zone;
042import org.ametys.web.repository.site.Site;
043import org.ametys.web.repository.sitemap.Sitemap;
044import org.ametys.web.service.ServiceExtensionPoint;
045import org.ametys.web.skin.Skin;
046import org.ametys.web.skin.SkinsManager;
047
048/**
049 * Page representing an UGC page.
050 */
051public class UGCPage implements Page
052{
053    private static final String __UGC_PAGE_TEMPLATE = "ugc-page";
054    
055    private Page _root;
056    private String _title;
057    private AmetysObjectResolver _resolver;
058    private UGCPageHandler _ugcPageHandler;
059    private SkinsManager _skinsManager;
060    private String _path;
061    private Content _ugcContent;
062    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _pageDataTypeExtensionPoint;
063    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneDataTypeExtensionPoint;
064    private ServiceExtensionPoint _serviceExtensionPoint;
065    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneItemDataTypeExtensionPoint;
066    
067    /**
068     * Constructor.
069     * @param root the root page.
070     * @param syncContent the synchronized content
071     * @param path the path
072     * @param resolver the {@link AmetysObjectResolver}.
073     * @param ugcPageHandler the ugc page handler
074     * @param skinsManager the skins manager
075     * @param pageDataTypeExtensionPoint the extension point with available data types for pages
076     * @param zoneDataTypeExtensionPoint the extension point with available data types for zones
077     * @param serviceExtensionPoint the service extension point
078     * @param zoneItemDataTypeExtensionPoint the extension point with available data types for zone items
079     */
080    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)
081    {
082        _root = root;
083        _path = path;
084        _resolver = resolver;
085        _ugcPageHandler = ugcPageHandler;
086        _skinsManager = skinsManager;
087        _ugcContent = syncContent;
088        _title = _ugcContent.getTitle(new Locale(root.getSitemapName()));
089        
090        _pageDataTypeExtensionPoint = pageDataTypeExtensionPoint;
091        _zoneDataTypeExtensionPoint = zoneDataTypeExtensionPoint;
092        _serviceExtensionPoint = serviceExtensionPoint;
093        _zoneItemDataTypeExtensionPoint = zoneItemDataTypeExtensionPoint;
094    }
095    
096    /**
097     * Returns the associated UGC {@link Content}.
098     * @return the associated UGC {@link Content}.
099     */
100    public Content getUgcContent()
101    {
102        return _ugcContent;
103    }
104    
105    public int getDepth() throws AmetysRepositoryException
106    {
107        return _root.getDepth() + (_path.equals("_root") ? 1 : 2);
108    }
109
110    public Set<String> getReferers() throws AmetysRepositoryException
111    {
112        return null;
113    }
114
115    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
116    {
117        return null;
118    }
119
120    public String getTemplate() throws AmetysRepositoryException
121    {
122        Skin skin = _skinsManager.getSkin(getSite().getSkinId());
123        
124        if (skin.getTemplate(__UGC_PAGE_TEMPLATE) != null)
125        {
126            return __UGC_PAGE_TEMPLATE;
127        }
128        
129        return "page"; 
130    }
131
132    public String getTitle() throws AmetysRepositoryException
133    {
134        return _title;
135    }
136    
137    public String getLongTitle() throws AmetysRepositoryException
138    {
139        return _title;
140    }
141
142    public PageType getType() throws AmetysRepositoryException
143    {
144        return PageType.CONTAINER;
145    }
146
147    public String getURL() throws AmetysRepositoryException
148    {
149        throw new UnsupportedOperationException("#getURL is not supported on virtual ugc pages");
150    }
151
152    public LinkType getURLType() throws AmetysRepositoryException
153    {
154        throw new UnsupportedOperationException("#getURLType is not supported on virtual ugc pages");
155    }
156
157    public Zone getZone(String name) throws UnknownZoneException, AmetysRepositoryException
158    {
159        if (!"default".equals(name))
160        {
161            throw new IllegalArgumentException("Only the zone named 'default' is actually supported on virtual ugc pages.");
162        }
163        
164        return new UGCZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint);
165    }
166
167    public AmetysObjectIterable< ? extends Zone> getZones() throws AmetysRepositoryException
168    {
169        ArrayList<Zone> zones = new ArrayList<>();
170        zones.add(new UGCZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint));
171        return new CollectionIterable<>(zones);
172    }
173
174    public boolean hasZone(String name) throws AmetysRepositoryException
175    {
176        return "default".equals(name);
177    }
178
179    public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException
180    {
181        ArrayList<Page> children = new ArrayList<>();
182        return new CollectionIterable<>(children);
183    }
184
185    public String getPathInSitemap() throws AmetysRepositoryException
186    {
187        if (_path.equals("_root"))
188        {
189            return _root.getPathInSitemap() + "/" + getName();
190        }
191        else
192        {
193            return _root.getPathInSitemap() + "/" + _path + "/" + getName();
194        }
195    }
196
197    public Site getSite() throws AmetysRepositoryException
198    {
199        return _root.getSite();
200    }
201
202    public String getSiteName() throws AmetysRepositoryException
203    {
204        return _root.getSiteName();
205    }
206
207    public Sitemap getSitemap() throws AmetysRepositoryException
208    {
209        return _root.getSitemap();
210    }
211
212    public String getSitemapName() throws AmetysRepositoryException
213    {
214        return _root.getSitemapName();
215    }
216
217    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
218    {
219        if (path.isEmpty())
220        {
221            throw new AmetysRepositoryException("path must be non empty");
222        }
223        
224        return null;
225    }
226
227    @SuppressWarnings("unchecked")
228    public AmetysObjectIterable<? extends AmetysObject> getChildren() throws AmetysRepositoryException
229    {
230        return getChildrenPages();
231    }
232
233    public boolean hasChild(String name) throws AmetysRepositoryException
234    {
235        return false;
236    }
237    
238    public String getId() throws AmetysRepositoryException
239    {
240        return _ugcPageHandler.computePageId(_path, _root, _ugcContent);
241    }
242
243    public String getName() throws AmetysRepositoryException
244    {
245        return _ugcContent.getName();
246    }
247    
248    @SuppressWarnings("unchecked")
249    public Page getParent() throws AmetysRepositoryException
250    {
251        if (!_path.equals("_root"))
252        {
253            String name = _path;
254            Map<String, Map<String, String>> transitionalPageName = _ugcPageHandler.getTransitionalPage(_root);
255            Map<String, String> attributes = transitionalPageName.get(name);
256            String title = attributes.get(UGCPageHandler.ATTRIBUTE_TRANSITIONAL_PAGE_TITLE);
257            String metadataValue = attributes.get(UGCPageHandler.ATTRIBUTE_TRANSITIONAL_PAGE_METADATA_VALUE);
258            return new UGCTransitionalPage(_root, title, metadataValue, name, _resolver, _ugcPageHandler, _skinsManager, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint);
259        }
260        else
261        {
262            return _root;
263        }
264    }
265
266    public String getParentPath() throws AmetysRepositoryException
267    {
268        if (!_path.equals("_root"))
269        {
270            return _root.getPath() + "/" + _path;
271        }
272        else
273        {
274            return _root.getPath();
275        }
276    }
277
278    public String getPath() throws AmetysRepositoryException
279    {
280        return getParentPath() + "/" + getName();
281    }
282
283    public ModelLessDataHolder getDataHolder()
284    {
285        RepositoryData repositoryData = new MemoryRepositoryData(getName());
286        return new DefaultModelLessDataHolder(_pageDataTypeExtensionPoint, repositoryData);
287    }
288
289    public Set<String> getTags() throws AmetysRepositoryException
290    {
291        return Collections.emptySet();
292    }
293
294    public AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePage) throws AmetysRepositoryException
295    {
296        ArrayList<Page> children = new ArrayList<>();
297        return new CollectionIterable<>(children);
298    }
299
300    public boolean isVisible() throws AmetysRepositoryException
301    {
302        return true;
303    }
304
305    public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException
306    {
307        throw new UnknownAmetysObjectException("There is no child for ugc page");
308    }
309
310    public ModelAwareDataHolder getTemplateParametersHolder() throws AmetysRepositoryException
311    {
312        return null;
313    }
314}