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.List;
021import java.util.Set;
022import java.util.stream.Collectors;
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/**
050 * Page representing a transitional page.
051 */
052public class UGCTransitionalPage implements Page
053{
054    private static final String __UGC_TRANSITIONAL_PAGE_TEMPLATE = "ugc-transitional-page";
055    
056    private Page _root;
057    private String _path;
058    private String _title;
059    private String _metadataValue;
060    private AmetysObjectResolver _resolver;
061    private UGCPageHandler _ugcPageHandler;
062    private SkinsManager _skinsManager;
063
064    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _pageDataTypeExtensionPoint;
065    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneDataTypeExtensionPoint;
066    private ServiceExtensionPoint _serviceExtensionPoint;
067    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneItemDataTypeExtensionPoint;
068    
069    /**
070     * Constructor.
071     * @param root the user directory root page.
072     * @param title the page's title.
073     * @param metadataValue the metadata value
074     * @param resolver the {@link AmetysObjectResolver}.
075     * @param path the path
076     * @param userDirectoryPageHandler the user directory page handler component
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 UGCTransitionalPage(Page root, String title, String metadataValue, String path, AmetysObjectResolver resolver, UGCPageHandler userDirectoryPageHandler, SkinsManager skinsManager, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> pageDataTypeExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneDataTypeExtensionPoint, ServiceExtensionPoint serviceExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneItemDataTypeExtensionPoint)
084    {
085        _root = root;
086        _title = title;
087        _metadataValue = metadataValue;
088        _path = path;
089        _resolver = resolver;
090        _ugcPageHandler = userDirectoryPageHandler;
091        _skinsManager = skinsManager;
092        
093        _pageDataTypeExtensionPoint = pageDataTypeExtensionPoint;
094        _zoneDataTypeExtensionPoint = zoneDataTypeExtensionPoint;
095        _serviceExtensionPoint = serviceExtensionPoint;
096        _zoneItemDataTypeExtensionPoint = zoneItemDataTypeExtensionPoint;
097    }
098    
099    @Override
100    public int getDepth() throws AmetysRepositoryException
101    {
102        return _root.getDepth() + 1;
103    }
104
105    @Override
106    public Set<String> getReferers() throws AmetysRepositoryException
107    {
108        return null;
109    }
110
111    @Override
112    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
113    {
114        return null;
115    }
116
117    @Override
118    public String getTemplate() throws AmetysRepositoryException
119    {
120        Skin skin = _skinsManager.getSkin(getSite().getSkinId());
121        
122        if (skin.getTemplate(__UGC_TRANSITIONAL_PAGE_TEMPLATE) != null)
123        {
124            return __UGC_TRANSITIONAL_PAGE_TEMPLATE;
125        }
126        
127        return "page"; 
128    }
129
130    @Override
131    public String getTitle() throws AmetysRepositoryException
132    {
133        return _title;
134    }
135    
136    @Override
137    public String getLongTitle() throws AmetysRepositoryException
138    {
139        return _title;
140    }
141
142    @Override
143    public PageType getType() throws AmetysRepositoryException
144    {
145        return PageType.CONTAINER;
146    }
147
148    @Override
149    public String getURL() throws AmetysRepositoryException
150    {
151        throw new UnsupportedOperationException("getURL not supported on virtual ugc transitional pages");
152    }
153
154    @Override
155    public LinkType getURLType() throws AmetysRepositoryException
156    {
157        throw new UnsupportedOperationException("getURLType not supported on virtual ugc transitional pages");
158    }
159
160    @Override
161    public Zone getZone(String name) throws UnknownZoneException, AmetysRepositoryException
162    {
163        if (!"default".equals(name))
164        {
165            throw new IllegalArgumentException("Only the zone named 'default' is actually supported on virtual ugc transitional pages.");
166        }
167        
168        return new UGCTransitionalZone(this, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint);
169    }
170
171    @Override
172    public AmetysObjectIterable< ? extends Zone> getZones() throws AmetysRepositoryException
173    {
174        List<Zone> zones = new ArrayList<>();
175        zones.add(new UGCTransitionalZone(this, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint));
176        return new CollectionIterable<>(zones);
177    }
178
179    @Override
180    public boolean hasZone(String name) throws AmetysRepositoryException
181    {
182        return "default".equals(name);
183    }
184
185    @Override
186    public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException
187    {
188        ArrayList<Page> children = new ArrayList<>();
189        
190        AmetysObjectIterable<Content> contentsForTransitionalPage = _ugcPageHandler.getContentsForTransitionalPage(_root, _metadataValue);
191        for (Content content : contentsForTransitionalPage)
192        {
193            children.add(new UGCPage(_root, content, _path, _resolver, _ugcPageHandler, _skinsManager, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint));
194        }
195        
196        return new CollectionIterable<>(children);
197    }
198
199    @Override
200    public AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePage) throws AmetysRepositoryException
201    {
202        if (includeInvisiblePage)
203        {
204            return getChildrenPages();
205        }
206        else
207        {
208            ArrayList<Page> children = new ArrayList<>();
209            return new CollectionIterable<>(children);
210        }
211    }
212    
213    @Override
214    public String getPathInSitemap() throws AmetysRepositoryException
215    {
216        return _root.getPathInSitemap() + "/" + _path;
217    }
218
219    @Override
220    public Site getSite() throws AmetysRepositoryException
221    {
222        return _root.getSite();
223    }
224
225    @Override
226    public String getSiteName() throws AmetysRepositoryException
227    {
228        return _root.getSiteName();
229    }
230
231    @Override
232    public Sitemap getSitemap() throws AmetysRepositoryException
233    {
234        return _root.getSitemap();
235    }
236
237    @Override
238    public String getSitemapName() throws AmetysRepositoryException
239    {
240        return _root.getSitemapName();
241    }
242
243    @SuppressWarnings("unchecked")
244    @Override
245    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
246    {
247        if (path.isEmpty())
248        {
249            throw new AmetysRepositoryException("path must be non empty");
250        }
251        
252        String name = path;
253        AmetysObjectIterable<Content> contentsForTransitionalPage = _ugcPageHandler.getContentsForTransitionalPage(_root, _metadataValue);
254        List<Content> contentFilters = contentsForTransitionalPage.stream().filter(c -> c.getName().equals(name)).collect(Collectors.toList());
255        if (!contentFilters.isEmpty())
256        {
257            Content content = contentFilters.get(0);
258            return (A) new UGCPage(_root, content, _path, _resolver, _ugcPageHandler, _skinsManager, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint);
259        }
260        else
261        {
262            throw new UnknownAmetysObjectException("No ugc page for path " + path);
263        }
264    }
265
266    @SuppressWarnings("unchecked")
267    @Override
268    public AmetysObjectIterable<? extends AmetysObject> getChildren() throws AmetysRepositoryException
269    {
270        return getChildrenPages();
271    }
272
273    @Override
274    public boolean hasChild(String name) throws AmetysRepositoryException
275    {
276        AmetysObjectIterable<Content> contentsForTransitionalPage = _ugcPageHandler.getContentsForTransitionalPage(_root, _metadataValue);
277        List<Content> contentFilters = contentsForTransitionalPage.stream().filter(c -> c.getName().equals(name)).collect(Collectors.toList());
278        return !contentFilters.isEmpty();
279    }
280    
281    @Override
282    public String getId() throws AmetysRepositoryException
283    {
284        // E.g: ugctransitional://path?rootId=...
285        return "ugctransitional://" + _path + "?rootId=" + _root.getId();
286    }
287
288    @Override
289    public String getName() throws AmetysRepositoryException
290    {
291        return _path;
292    }
293    
294    @SuppressWarnings("unchecked")
295    @Override
296    public Page getParent() throws AmetysRepositoryException
297    {
298        return _root;
299    }
300
301    @Override
302    public String getParentPath() throws AmetysRepositoryException
303    {
304        return _root.getPath();
305    }
306
307    @Override
308    public String getPath() throws AmetysRepositoryException
309    {
310        return getParentPath() + "/" + getName();
311    }
312
313    public ModelLessDataHolder getDataHolder()
314    {
315        RepositoryData repositoryData = new MemoryRepositoryData(getName());
316        return new DefaultModelLessDataHolder(_pageDataTypeExtensionPoint, repositoryData);
317    }
318
319    @Override
320    public Set<String> getTags() throws AmetysRepositoryException
321    {
322        return Collections.emptySet();
323    }
324
325    @Override
326    public boolean isVisible() throws AmetysRepositoryException
327    {
328        return false;
329    }
330
331    @Override
332    public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException
333    {
334        return getChildrenPages().stream().collect(Collectors.toList()).get(index);
335    }
336    
337    public ModelAwareDataHolder getTemplateParametersHolder() throws AmetysRepositoryException
338    {
339        return null;
340    }
341}