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