001/*
002 *  Copyright 2011 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.blog.repository;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Collections;
021import java.util.NoSuchElementException;
022import java.util.Set;
023
024import org.ametys.cms.repository.Content;
025import org.ametys.plugins.blog.BlogCacheManager;
026import org.ametys.plugins.blog.BlogCacheManager.Post;
027import org.ametys.plugins.explorer.resources.ResourceCollection;
028import org.ametys.plugins.repository.AmetysObject;
029import org.ametys.plugins.repository.AmetysObjectIterable;
030import org.ametys.plugins.repository.AmetysObjectIterator;
031import org.ametys.plugins.repository.AmetysObjectResolver;
032import org.ametys.plugins.repository.AmetysRepositoryException;
033import org.ametys.plugins.repository.CollectionIterable;
034import org.ametys.plugins.repository.EmptyIterable;
035import org.ametys.plugins.repository.UnknownAmetysObjectException;
036import org.ametys.plugins.repository.metadata.CompositeMetadata;
037import org.ametys.web.repository.page.Page;
038import org.ametys.web.repository.page.PagesContainer;
039import org.ametys.web.repository.page.UnknownZoneException;
040import org.ametys.web.repository.page.Zone;
041import org.ametys.web.repository.site.Site;
042import org.ametys.web.repository.sitemap.Sitemap;
043import org.ametys.web.skin.SkinsManager;
044
045/**
046 * Virtual page representing the Post list page.
047 */
048public class VirtualPostsPage implements Page
049{
050    
051    /** The page name. */
052    public static final String NAME = "posts";
053    
054    private AmetysObjectResolver _resolver;
055    private BlogCacheManager _cacheManager;
056    private SkinsManager _skinsManager;
057    private PagesContainer _root;
058    private String _title;
059    
060    /**
061     * Constructor.
062     * @param resolver the {@link AmetysObjectResolver}.
063     * @param cacheManager the {@link AmetysObjectResolver}.
064     * @param skinsManager the skins manager
065     * @param root the blog root page.
066     * @param title the page's title.
067     */
068    public VirtualPostsPage(AmetysObjectResolver resolver, BlogCacheManager cacheManager, SkinsManager skinsManager, String title, PagesContainer root)
069    {
070        _resolver = resolver;
071        _cacheManager = cacheManager;
072        _skinsManager = skinsManager;
073        _root = root;
074        _title = title;
075    }
076    
077    @Override
078    public int getDepth() throws AmetysRepositoryException
079    {
080        int depth = 0;
081        if (_root instanceof Page)
082        {
083            depth = ((Page) _root).getDepth();
084        }
085        
086        return depth + 1;
087    }
088
089    @Override
090    public Set<String> getReferers() throws AmetysRepositoryException
091    {
092        return null;
093    }
094
095    @Override
096    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
097    {
098        return null;
099    }
100
101    @Override
102    public String getTemplate() throws AmetysRepositoryException
103    {
104        return "";
105    }
106
107    @Override
108    public String getTitle() throws AmetysRepositoryException
109    {
110        return _title;
111    }
112    
113    @Override
114    public String getLongTitle() throws AmetysRepositoryException
115    {
116        return _title;
117    }
118
119    @Override
120    public PageType getType() throws AmetysRepositoryException
121    {
122        return PageType.NODE;
123    }
124
125    @Override
126    public String getURL() throws AmetysRepositoryException
127    {
128        throw new UnsupportedOperationException("getURL not supported on virtual blog pages");
129    }
130
131    @Override
132    public LinkType getURLType() throws AmetysRepositoryException
133    {
134        throw new UnsupportedOperationException("getURLType not supported on virtual blog pages");
135    }
136
137    @Override
138    public Zone getZone(String name) throws UnknownZoneException, AmetysRepositoryException
139    {
140        throw new UnknownZoneException("There is no zone on the blog years page.");
141    }
142
143    @Override
144    public AmetysObjectIterable< ? extends Zone> getZones() throws AmetysRepositoryException
145    {
146        return new EmptyIterable<>();
147    }
148
149    @Override
150    public boolean hasZone(String name) throws AmetysRepositoryException
151    {
152        return false;
153    }
154
155    @Override
156    public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException
157    {
158        ArrayList<Page> children = new ArrayList<>();
159        
160        Collection<Post> posts = _cacheManager.getSortedPosts(getSiteName(), getSitemapName());
161        
162        for (Post post : posts)
163        {
164            Content postContent = _resolver.resolveById(post.getId());
165            
166            VirtualPostPage page = new VirtualPostPage(_resolver, _skinsManager, _root, postContent, NAME);
167            
168            children.add(page);
169        }
170        
171        // TODO
172        
173        return new CollectionIterable<>(children);
174    }
175
176    @Override
177    public AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePages) throws AmetysRepositoryException
178    {
179        return getChildrenPages();
180    }
181    
182    @Override
183    public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException
184    {
185        if (index < 0)
186        {
187            throw new AmetysRepositoryException("Child page index cannot be negative");
188        }
189        
190        AmetysObjectIterable< ? extends Page> childPages = getChildrenPages();
191        AmetysObjectIterator< ? extends Page> it = childPages.iterator();
192        
193        try
194        {
195            it.skip(index);
196            return it.next();
197        }
198        catch (NoSuchElementException e)
199        {
200            throw new UnknownAmetysObjectException("There's no child page at index " + index + " for page " + this.getId());
201        }
202    }
203    
204    @Override
205    public String getPathInSitemap() throws AmetysRepositoryException
206    {
207        StringBuilder path = new StringBuilder(_root.getPathInSitemap());
208        if (path.length() > 0)
209        {
210            path.append('/');
211        }
212        path.append(NAME);
213        
214        return path.toString();
215    }
216
217    @Override
218    public Site getSite() throws AmetysRepositoryException
219    {
220        return _root.getSite();
221    }
222
223    @Override
224    public String getSiteName() throws AmetysRepositoryException
225    {
226        return _root.getSiteName();
227    }
228
229    @Override
230    public Sitemap getSitemap() throws AmetysRepositoryException
231    {
232        return _root.getSitemap();
233    }
234
235    @Override
236    public String getSitemapName() throws AmetysRepositoryException
237    {
238        return _root.getSitemapName();
239    }
240
241    @SuppressWarnings("unchecked")
242    @Override
243    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
244    {
245        if (path.isEmpty())
246        {
247            throw new AmetysRepositoryException("Path must be non empty");
248        }
249        
250//        int slashPos = path.indexOf('/');
251//        int questionPos = path.indexOf('?', slashPos);
252//        int ampPos = path.indexOf('&', questionPos);
253            
254//        String childName = slashPos == -1 ? path : path.substring(0, slashPos);
255//        String rootId = path.substring(questionPos + "?rootId=".length(), ampPos);
256//        String postId = path.substring(ampPos + "&postId=".length());
257        
258        int slashPos = path.indexOf('/');
259        
260        String childName = slashPos == -1 ? path : path.substring(0, slashPos);
261        
262        Post post = _cacheManager.getPostByName(getSiteName(), getSitemapName(), childName);
263        if (post == null)
264        {
265            throw new UnknownAmetysObjectException(path + " is not a valid post page.");
266        }
267        
268        Content postContent = _resolver.resolveById(post.getId());
269        
270//        Content postContent = _resolver.resolveById(postId);
271        
272        VirtualPostPage page = new VirtualPostPage(_resolver, _skinsManager, _root, postContent, NAME);
273        
274        if (slashPos == -1)
275        {
276            return (A) page;
277        }
278        else
279        {
280            return (A) page.getChild(path.substring(slashPos + 1));
281        }
282    }
283
284    @SuppressWarnings("unchecked")
285    @Override
286    public AmetysObjectIterable<? extends AmetysObject> getChildren() throws AmetysRepositoryException
287    {
288        return getChildrenPages();
289    }
290
291    @Override
292    public boolean hasChild(String name) throws AmetysRepositoryException
293    {
294        return _cacheManager.hasPostByName(getSiteName(), getSitemapName(), name);
295    }
296    
297    @Override
298    public String getId() throws AmetysRepositoryException
299    {
300        return "blog-category://" + NAME + "?rootId=" + _root.getId();
301    }
302
303    @Override
304    public String getName() throws AmetysRepositoryException
305    {
306        return NAME;
307    }
308
309    @SuppressWarnings("unchecked")
310    @Override
311    public PagesContainer getParent() throws AmetysRepositoryException
312    {
313        return _root;
314    }
315
316    @Override
317    public String getParentPath() throws AmetysRepositoryException
318    {
319        return _root.getPath();
320    }
321
322    @Override
323    public String getPath() throws AmetysRepositoryException
324    {
325        StringBuilder buff = new StringBuilder(getParentPath());
326        if (!getParentPath().isEmpty())
327        {
328            buff.append('/');
329        }
330        buff.append(NAME);
331        
332        return buff.toString();
333    }
334
335    @Override
336    public CompositeMetadata getMetadataHolder()
337    {
338        return new StaticCompositeMetadata();
339    }
340
341    @Override
342    public Set<String> getTags() throws AmetysRepositoryException
343    {
344        return Collections.emptySet();
345    }
346    
347    @Override
348    public boolean isVisible() throws AmetysRepositoryException
349    {
350        return true;
351    }
352}