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.Collections;
019import java.util.Set;
020
021import org.ametys.cms.repository.Content;
022import org.ametys.plugins.explorer.resources.ResourceCollection;
023import org.ametys.plugins.repository.AmetysObject;
024import org.ametys.plugins.repository.AmetysObjectIterable;
025import org.ametys.plugins.repository.AmetysObjectResolver;
026import org.ametys.plugins.repository.AmetysRepositoryException;
027import org.ametys.plugins.repository.EmptyIterable;
028import org.ametys.plugins.repository.UnknownAmetysObjectException;
029import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
030import org.ametys.plugins.repository.data.holder.ModelLessDataHolder;
031import org.ametys.plugins.repository.data.holder.impl.DefaultModelLessDataHolder;
032import org.ametys.plugins.repository.data.repositorydata.RepositoryData;
033import org.ametys.plugins.repository.data.repositorydata.impl.MemoryRepositoryData;
034import org.ametys.plugins.repository.data.type.RepositoryModelItemType;
035import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint;
036import org.ametys.web.repository.page.Page;
037import org.ametys.web.repository.page.PagesContainer;
038import org.ametys.web.repository.page.Zone;
039import org.ametys.web.repository.site.Site;
040import org.ametys.web.repository.sitemap.Sitemap;
041import org.ametys.web.skin.Skin;
042import org.ametys.web.skin.SkinsManager;
043
044/**
045 * Page representing a post.
046 */
047public class VirtualPostPage extends AbstractBlogPage
048{
049    private PagesContainer _root;
050    private Content _post;
051    private String _path;
052    private SkinsManager _skinsManager;
053    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _pageDataTypeExtensionPoint;
054    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneDataTypeExtensionPoint;
055    private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneItemDataTypeExtensionPoint;
056    
057    /**
058     * Constructor.
059     * @param skinsManager the skins manager
060     * @param resolver the {@link AmetysObjectResolver}.
061     * @param root the blog root page.
062     * @param post the post.
063     * @param path path from the virtual root
064     * @param pageDataTypeExtensionPoint the extension point with available data types for pages
065     * @param zoneDataTypeExtensionPoint the extension point with available data types for zones
066     * @param zoneItemDataTypeExtensionPoint the extension point with available data types for zone items
067     */
068    public VirtualPostPage(AmetysObjectResolver resolver, SkinsManager skinsManager, PagesContainer root, Content post, String path, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> pageDataTypeExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneDataTypeExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneItemDataTypeExtensionPoint)
069    {
070        _root = root;
071        _skinsManager = skinsManager;
072        _post = post;
073        _path = path;
074        _pageDataTypeExtensionPoint = pageDataTypeExtensionPoint;
075        _zoneDataTypeExtensionPoint = zoneDataTypeExtensionPoint;
076        _zoneItemDataTypeExtensionPoint = zoneItemDataTypeExtensionPoint;
077    }
078    
079    /**
080     * Returns the associated {@link Content}.
081     * @return the associated {@link Content}.
082     */
083    public Content getPost()
084    {
085        return _post;
086    }
087    
088    @Override
089    public int getDepth() throws AmetysRepositoryException
090    {
091        int depth = 0;
092        if (_root instanceof Page)
093        {
094            depth = ((Page) _root).getDepth();
095        }
096        
097        return depth + _path.split("/").length;
098    }
099
100    @Override
101    public Set<String> getReferers() throws AmetysRepositoryException
102    {
103        throw new UnsupportedOperationException("getReferers not supported on virtual post pages");
104    }
105
106    @Override
107    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
108    {
109        return null;
110    }
111    
112    @Override
113    public String getTitle() throws AmetysRepositoryException
114    {
115        return _post.getTitle();
116    }
117
118    @Override
119    public String getLongTitle() throws AmetysRepositoryException
120    {
121        return _post.getTitle();
122    }
123    
124    @Override
125    public String getURL() throws AmetysRepositoryException
126    {
127        throw new UnsupportedOperationException("getURL not supported on virtual post pages");
128    }
129
130    @Override
131    public LinkType getURLType() throws AmetysRepositoryException
132    {
133        throw new UnsupportedOperationException("getURLType not supported on virtual post pages");
134    }
135    
136    @Override
137    protected Zone getDefaultZone()
138    {
139        return new PostZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint);
140    }
141    
142    @Override
143    public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException
144    {
145        return new EmptyIterable<>();
146    }
147    
148    @Override
149    public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException
150    {
151        throw new UnknownAmetysObjectException("There's no child page at index " + index + " for page " + this.getId());
152    }
153
154    @Override
155    public String getPathInSitemap() throws AmetysRepositoryException
156    {
157        String rootPath = _root.getPathInSitemap();
158        
159        StringBuilder buff = new StringBuilder(rootPath);
160        if (!rootPath.isEmpty())
161        {
162            buff.append('/');
163        }
164        buff.append(_path).append('/').append(_post.getName());
165        
166        return buff.toString();
167    }
168
169    @Override
170    public Site getSite() throws AmetysRepositoryException
171    {
172        return _root.getSite();
173    }
174
175    @Override
176    public String getSiteName() throws AmetysRepositoryException
177    {
178        return _root.getSiteName();
179    }
180
181    @Override
182    public Sitemap getSitemap() throws AmetysRepositoryException
183    {
184        return _root.getSitemap();
185    }
186
187    @Override
188    public String getSitemapName() throws AmetysRepositoryException
189    {
190        return _root.getSitemapName();
191    }
192
193    @Override
194    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
195    {
196        throw new UnknownAmetysObjectException("Unknown child page '" + path + "' for page " + getId());
197    }
198    
199    @SuppressWarnings("unchecked")
200    @Override
201    public AmetysObjectIterable<? extends Page> getChildren() throws AmetysRepositoryException
202    {
203        return new EmptyIterable<>();
204    }
205    
206    @Override
207    public AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePages) throws AmetysRepositoryException
208    {
209        return getChildrenPages();
210    }
211
212    @Override
213    public boolean hasChild(String name) throws AmetysRepositoryException
214    {
215        return false;
216    }
217    
218    @Override
219    public String getId() throws AmetysRepositoryException
220    {
221        return "post://" + _path + "?rootId=" + _root.getId() + "&postId=" + _post.getId();
222    }
223
224    @Override
225    public String getName() throws AmetysRepositoryException
226    {
227        return _post.getName();
228    }
229
230    @SuppressWarnings("unchecked")
231    @Override
232    public Page getParent() throws AmetysRepositoryException
233    {
234        return _root.getChild(_path);
235    }
236
237    @Override
238    public String getParentPath() throws AmetysRepositoryException
239    {
240        StringBuilder path = new StringBuilder(_root.getPath());
241        if (path.length() > 0)
242        {
243            path.append('/');
244        }
245        
246        path.append(_path);
247        
248        return path.toString();
249    }
250
251    @Override
252    public String getPath() throws AmetysRepositoryException
253    {
254        return getParentPath() + "/" + _post.getName();
255    }
256
257    public ModelLessDataHolder getDataHolder()
258    {
259        RepositoryData repositoryData = new MemoryRepositoryData(getName());
260        return new DefaultModelLessDataHolder(_pageDataTypeExtensionPoint, repositoryData);
261    }
262
263    @Override
264    public Set<String> getTags() throws AmetysRepositoryException
265    {
266        return Collections.emptySet();
267    }
268    
269    @Override
270    public String getTemplate() throws AmetysRepositoryException
271    {
272        Skin skin = _skinsManager.getSkin(getSite().getSkinId());
273        
274        if (skin.getTemplate(BLOG_POST_TEMPLATE) != null)
275        {
276            return BLOG_POST_TEMPLATE;
277        }
278        
279        return super.getTemplate(); 
280    }
281
282    @Override
283    public boolean isVisible() throws AmetysRepositoryException
284    {
285        return true;
286    }
287    
288    public ModelAwareDataHolder getTemplateParametersHolder() throws AmetysRepositoryException
289    {
290        return null;
291    }
292}