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