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