001/* 002 * Copyright 2018 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.ugc.page; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.List; 021import java.util.Set; 022import java.util.stream.Collectors; 023 024import org.ametys.cms.repository.Content; 025import org.ametys.plugins.explorer.resources.ResourceCollection; 026import org.ametys.plugins.repository.AmetysObject; 027import org.ametys.plugins.repository.AmetysObjectIterable; 028import org.ametys.plugins.repository.AmetysObjectResolver; 029import org.ametys.plugins.repository.AmetysRepositoryException; 030import org.ametys.plugins.repository.CollectionIterable; 031import org.ametys.plugins.repository.UnknownAmetysObjectException; 032import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 033import org.ametys.plugins.repository.data.holder.ModelLessDataHolder; 034import org.ametys.plugins.repository.data.holder.impl.DefaultModelLessDataHolder; 035import org.ametys.plugins.repository.data.repositorydata.RepositoryData; 036import org.ametys.plugins.repository.data.repositorydata.impl.MemoryRepositoryData; 037import org.ametys.plugins.repository.data.type.RepositoryModelItemType; 038import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; 039import org.ametys.web.repository.page.Page; 040import org.ametys.web.repository.page.UnknownZoneException; 041import org.ametys.web.repository.page.Zone; 042import org.ametys.web.repository.site.Site; 043import org.ametys.web.repository.sitemap.Sitemap; 044import org.ametys.web.service.ServiceExtensionPoint; 045import org.ametys.web.skin.Skin; 046import org.ametys.web.skin.SkinsManager; 047 048 049/** 050 * Page representing a transitional page. 051 */ 052public class UGCTransitionalPage implements Page 053{ 054 private static final String __UGC_TRANSITIONAL_PAGE_TEMPLATE = "ugc-transitional-page"; 055 056 private Page _root; 057 private String _path; 058 private String _title; 059 private String _metadataValue; 060 private AmetysObjectResolver _resolver; 061 private UGCPageHandler _ugcPageHandler; 062 private SkinsManager _skinsManager; 063 064 private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _pageDataTypeExtensionPoint; 065 private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneDataTypeExtensionPoint; 066 private ServiceExtensionPoint _serviceExtensionPoint; 067 private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneItemDataTypeExtensionPoint; 068 069 /** 070 * Constructor. 071 * @param root the user directory root page. 072 * @param title the page's title. 073 * @param metadataValue the metadata value 074 * @param resolver the {@link AmetysObjectResolver}. 075 * @param path the path 076 * @param userDirectoryPageHandler the user directory page handler component 077 * @param skinsManager the skins manager 078 * @param pageDataTypeExtensionPoint the extension point with available data types for pages 079 * @param zoneDataTypeExtensionPoint the extension point with available data types for zones 080 * @param serviceExtensionPoint the service extension point 081 * @param zoneItemDataTypeExtensionPoint the extension point with available data types for zone items 082 */ 083 public UGCTransitionalPage(Page root, String title, String metadataValue, String path, AmetysObjectResolver resolver, UGCPageHandler userDirectoryPageHandler, SkinsManager skinsManager, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> pageDataTypeExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneDataTypeExtensionPoint, ServiceExtensionPoint serviceExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneItemDataTypeExtensionPoint) 084 { 085 _root = root; 086 _title = title; 087 _metadataValue = metadataValue; 088 _path = path; 089 _resolver = resolver; 090 _ugcPageHandler = userDirectoryPageHandler; 091 _skinsManager = skinsManager; 092 093 _pageDataTypeExtensionPoint = pageDataTypeExtensionPoint; 094 _zoneDataTypeExtensionPoint = zoneDataTypeExtensionPoint; 095 _serviceExtensionPoint = serviceExtensionPoint; 096 _zoneItemDataTypeExtensionPoint = zoneItemDataTypeExtensionPoint; 097 } 098 099 @Override 100 public int getDepth() throws AmetysRepositoryException 101 { 102 return _root.getDepth() + 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 Skin skin = _skinsManager.getSkin(getSite().getSkinId()); 121 122 if (skin.getTemplate(__UGC_TRANSITIONAL_PAGE_TEMPLATE) != null) 123 { 124 return __UGC_TRANSITIONAL_PAGE_TEMPLATE; 125 } 126 127 return "page"; 128 } 129 130 @Override 131 public String getTitle() throws AmetysRepositoryException 132 { 133 return _title; 134 } 135 136 @Override 137 public String getLongTitle() throws AmetysRepositoryException 138 { 139 return _title; 140 } 141 142 @Override 143 public PageType getType() throws AmetysRepositoryException 144 { 145 return PageType.CONTAINER; 146 } 147 148 @Override 149 public String getURL() throws AmetysRepositoryException 150 { 151 throw new UnsupportedOperationException("getURL not supported on virtual ugc transitional pages"); 152 } 153 154 @Override 155 public LinkType getURLType() throws AmetysRepositoryException 156 { 157 throw new UnsupportedOperationException("getURLType not supported on virtual ugc transitional pages"); 158 } 159 160 @Override 161 public Zone getZone(String name) throws UnknownZoneException, AmetysRepositoryException 162 { 163 if (!"default".equals(name)) 164 { 165 throw new IllegalArgumentException("Only the zone named 'default' is actually supported on virtual ugc transitional pages."); 166 } 167 168 return new UGCTransitionalZone(this, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint); 169 } 170 171 @Override 172 public AmetysObjectIterable< ? extends Zone> getZones() throws AmetysRepositoryException 173 { 174 List<Zone> zones = new ArrayList<>(); 175 zones.add(new UGCTransitionalZone(this, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint)); 176 return new CollectionIterable<>(zones); 177 } 178 179 @Override 180 public boolean hasZone(String name) throws AmetysRepositoryException 181 { 182 return "default".equals(name); 183 } 184 185 @Override 186 public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException 187 { 188 ArrayList<Page> children = new ArrayList<>(); 189 190 AmetysObjectIterable<Content> contentsForTransitionalPage = _ugcPageHandler.getContentsForTransitionalPage(_root, _metadataValue); 191 for (Content content : contentsForTransitionalPage) 192 { 193 children.add(new UGCPage(_root, content, _path, _resolver, _ugcPageHandler, _skinsManager, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint)); 194 } 195 196 return new CollectionIterable<>(children); 197 } 198 199 @Override 200 public AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePage) throws AmetysRepositoryException 201 { 202 if (includeInvisiblePage) 203 { 204 return getChildrenPages(); 205 } 206 else 207 { 208 ArrayList<Page> children = new ArrayList<>(); 209 return new CollectionIterable<>(children); 210 } 211 } 212 213 @Override 214 public String getPathInSitemap() throws AmetysRepositoryException 215 { 216 return _root.getPathInSitemap() + "/" + _path; 217 } 218 219 @Override 220 public Site getSite() throws AmetysRepositoryException 221 { 222 return _root.getSite(); 223 } 224 225 @Override 226 public String getSiteName() throws AmetysRepositoryException 227 { 228 return _root.getSiteName(); 229 } 230 231 @Override 232 public Sitemap getSitemap() throws AmetysRepositoryException 233 { 234 return _root.getSitemap(); 235 } 236 237 @Override 238 public String getSitemapName() throws AmetysRepositoryException 239 { 240 return _root.getSitemapName(); 241 } 242 243 @SuppressWarnings("unchecked") 244 @Override 245 public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException 246 { 247 if (path.isEmpty()) 248 { 249 throw new AmetysRepositoryException("path must be non empty"); 250 } 251 252 String name = path; 253 AmetysObjectIterable<Content> contentsForTransitionalPage = _ugcPageHandler.getContentsForTransitionalPage(_root, _metadataValue); 254 List<Content> contentFilters = contentsForTransitionalPage.stream().filter(c -> c.getName().equals(name)).collect(Collectors.toList()); 255 if (!contentFilters.isEmpty()) 256 { 257 Content content = contentFilters.get(0); 258 return (A) new UGCPage(_root, content, _path, _resolver, _ugcPageHandler, _skinsManager, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint); 259 } 260 else 261 { 262 throw new UnknownAmetysObjectException("No ugc page for path " + path); 263 } 264 } 265 266 @SuppressWarnings("unchecked") 267 @Override 268 public AmetysObjectIterable<? extends AmetysObject> getChildren() throws AmetysRepositoryException 269 { 270 return getChildrenPages(); 271 } 272 273 @Override 274 public boolean hasChild(String name) throws AmetysRepositoryException 275 { 276 AmetysObjectIterable<Content> contentsForTransitionalPage = _ugcPageHandler.getContentsForTransitionalPage(_root, _metadataValue); 277 List<Content> contentFilters = contentsForTransitionalPage.stream().filter(c -> c.getName().equals(name)).collect(Collectors.toList()); 278 return !contentFilters.isEmpty(); 279 } 280 281 @Override 282 public String getId() throws AmetysRepositoryException 283 { 284 // E.g: ugctransitional://path?rootId=... 285 return "ugctransitional://" + _path + "?rootId=" + _root.getId(); 286 } 287 288 @Override 289 public String getName() throws AmetysRepositoryException 290 { 291 return _path; 292 } 293 294 @SuppressWarnings("unchecked") 295 @Override 296 public Page getParent() throws AmetysRepositoryException 297 { 298 return _root; 299 } 300 301 @Override 302 public String getParentPath() throws AmetysRepositoryException 303 { 304 return _root.getPath(); 305 } 306 307 @Override 308 public String getPath() throws AmetysRepositoryException 309 { 310 return getParentPath() + "/" + getName(); 311 } 312 313 public ModelLessDataHolder getDataHolder() 314 { 315 RepositoryData repositoryData = new MemoryRepositoryData(getName()); 316 return new DefaultModelLessDataHolder(_pageDataTypeExtensionPoint, repositoryData); 317 } 318 319 @Override 320 public Set<String> getTags() throws AmetysRepositoryException 321 { 322 return Collections.emptySet(); 323 } 324 325 @Override 326 public boolean isVisible() throws AmetysRepositoryException 327 { 328 return false; 329 } 330 331 @Override 332 public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException 333 { 334 return getChildrenPages().stream().collect(Collectors.toList()).get(index); 335 } 336 337 public ModelAwareDataHolder getTemplateParametersHolder() throws AmetysRepositoryException 338 { 339 return null; 340 } 341}