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