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