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