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