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.Locale; 021import java.util.Map; 022import java.util.Set; 023 024import org.ametys.cms.repository.Content; 025import org.ametys.core.group.GroupIdentity; 026import org.ametys.core.user.UserIdentity; 027import org.ametys.plugins.explorer.resources.ResourceCollection; 028import org.ametys.plugins.repository.ACLAmetysObject; 029import org.ametys.plugins.repository.AmetysObject; 030import org.ametys.plugins.repository.AmetysObjectIterable; 031import org.ametys.plugins.repository.AmetysObjectResolver; 032import org.ametys.plugins.repository.AmetysRepositoryException; 033import org.ametys.plugins.repository.CollectionIterable; 034import org.ametys.plugins.repository.UnknownAmetysObjectException; 035import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 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.UnknownZoneException; 044import org.ametys.web.repository.page.Zone; 045import org.ametys.web.repository.site.Site; 046import org.ametys.web.repository.sitemap.Sitemap; 047import org.ametys.web.service.ServiceExtensionPoint; 048import org.ametys.web.skin.Skin; 049import org.ametys.web.skin.SkinsManager; 050 051/** 052 * Page representing an UGC page. 053 */ 054public class UGCPage implements Page, ACLAmetysObject 055{ 056 private static final String __UGC_PAGE_TEMPLATE = "ugc-page"; 057 058 private Page _root; 059 private String _title; 060 private AmetysObjectResolver _resolver; 061 private UGCPageHandler _ugcPageHandler; 062 private SkinsManager _skinsManager; 063 private String _path; 064 private Content _ugcContent; 065 private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _pageDataTypeExtensionPoint; 066 private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneDataTypeExtensionPoint; 067 private ServiceExtensionPoint _serviceExtensionPoint; 068 private AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> _zoneItemDataTypeExtensionPoint; 069 070 /** 071 * Constructor. 072 * @param root the root page. 073 * @param syncContent the synchronized content 074 * @param path the path 075 * @param resolver the {@link AmetysObjectResolver}. 076 * @param ugcPageHandler the ugc page handler 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 UGCPage(Page root, Content syncContent, String path, AmetysObjectResolver resolver, UGCPageHandler ugcPageHandler, SkinsManager skinsManager, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> pageDataTypeExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneDataTypeExtensionPoint, ServiceExtensionPoint serviceExtensionPoint, AbstractThreadSafeComponentExtensionPoint<RepositoryModelItemType> zoneItemDataTypeExtensionPoint) 084 { 085 _root = root; 086 _path = path; 087 _resolver = resolver; 088 _ugcPageHandler = ugcPageHandler; 089 _skinsManager = skinsManager; 090 _ugcContent = syncContent; 091 _title = _ugcContent.getTitle(new Locale(root.getSitemapName())); 092 093 _pageDataTypeExtensionPoint = pageDataTypeExtensionPoint; 094 _zoneDataTypeExtensionPoint = zoneDataTypeExtensionPoint; 095 _serviceExtensionPoint = serviceExtensionPoint; 096 _zoneItemDataTypeExtensionPoint = zoneItemDataTypeExtensionPoint; 097 } 098 099 /** 100 * Returns the associated synchronizable {@link Content}. 101 * @return the associated synchronizable {@link Content}. 102 */ 103 public Content getSyncContent() 104 { 105 return _ugcContent; 106 } 107 108 @Override 109 public int getDepth() throws AmetysRepositoryException 110 { 111 return _root.getDepth() + (_path.equals("_root") ? 1 : 2); 112 } 113 114 @Override 115 public Set<String> getReferers() throws AmetysRepositoryException 116 { 117 return null; 118 } 119 120 @Override 121 public ResourceCollection getRootAttachments() throws AmetysRepositoryException 122 { 123 return null; 124 } 125 126 @Override 127 public String getTemplate() throws AmetysRepositoryException 128 { 129 Skin skin = _skinsManager.getSkin(getSite().getSkinId()); 130 131 if (skin.getTemplate(__UGC_PAGE_TEMPLATE) != null) 132 { 133 return __UGC_PAGE_TEMPLATE; 134 } 135 136 return "page"; 137 } 138 139 @Override 140 public String getTitle() throws AmetysRepositoryException 141 { 142 return _title; 143 } 144 145 @Override 146 public String getLongTitle() throws AmetysRepositoryException 147 { 148 return _title; 149 } 150 151 @Override 152 public PageType getType() throws AmetysRepositoryException 153 { 154 return PageType.CONTAINER; 155 } 156 157 @Override 158 public String getURL() throws AmetysRepositoryException 159 { 160 throw new UnsupportedOperationException("#getURL is not supported on virtual ugc pages"); 161 } 162 163 @Override 164 public LinkType getURLType() throws AmetysRepositoryException 165 { 166 throw new UnsupportedOperationException("#getURLType is not supported on virtual ugc pages"); 167 } 168 169 @Override 170 public Zone getZone(String name) throws UnknownZoneException, AmetysRepositoryException 171 { 172 if (!"default".equals(name)) 173 { 174 throw new IllegalArgumentException("Only the zone named 'default' is actually supported on virtual ugc pages."); 175 } 176 177 return new UGCZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint); 178 } 179 180 @Override 181 public AmetysObjectIterable< ? extends Zone> getZones() throws AmetysRepositoryException 182 { 183 ArrayList<Zone> zones = new ArrayList<>(); 184 zones.add(new UGCZone(this, _zoneDataTypeExtensionPoint, _zoneItemDataTypeExtensionPoint)); 185 return new CollectionIterable<>(zones); 186 } 187 188 @Override 189 public boolean hasZone(String name) throws AmetysRepositoryException 190 { 191 return "default".equals(name); 192 } 193 194 @Override 195 public AmetysObjectIterable<? extends Page> getChildrenPages() throws AmetysRepositoryException 196 { 197 ArrayList<Page> children = new ArrayList<>(); 198 return new CollectionIterable<>(children); 199 } 200 201 @Override 202 public String getPathInSitemap() throws AmetysRepositoryException 203 { 204 if (_path.equals("_root")) 205 { 206 return _root.getPathInSitemap() + "/" + getName(); 207 } 208 else 209 { 210 return _root.getPathInSitemap() + "/" + _path + "/" + getName(); 211 } 212 } 213 214 @Override 215 public Site getSite() throws AmetysRepositoryException 216 { 217 return _root.getSite(); 218 } 219 220 @Override 221 public String getSiteName() throws AmetysRepositoryException 222 { 223 return _root.getSiteName(); 224 } 225 226 @Override 227 public Sitemap getSitemap() throws AmetysRepositoryException 228 { 229 return _root.getSitemap(); 230 } 231 232 @Override 233 public String getSitemapName() throws AmetysRepositoryException 234 { 235 return _root.getSitemapName(); 236 } 237 238 @Override 239 public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException 240 { 241 if (path.isEmpty()) 242 { 243 throw new AmetysRepositoryException("path must be non empty"); 244 } 245 246 return null; 247 } 248 249 @SuppressWarnings("unchecked") 250 @Override 251 public AmetysObjectIterable<? extends AmetysObject> getChildren() throws AmetysRepositoryException 252 { 253 return getChildrenPages(); 254 } 255 256 @Override 257 public boolean hasChild(String name) throws AmetysRepositoryException 258 { 259 return false; 260 } 261 262 @Override 263 public String getId() throws AmetysRepositoryException 264 { 265 return _ugcPageHandler.computePageId(_path, _root, _ugcContent); 266 } 267 268 @Override 269 public String getName() throws AmetysRepositoryException 270 { 271 return _ugcContent.getName(); 272 } 273 274 @SuppressWarnings("unchecked") 275 @Override 276 public Page getParent() throws AmetysRepositoryException 277 { 278 if (!_path.equals("_root")) 279 { 280 String name = _path; 281 Map<String, Map<String, String>> transitionalPageName = _ugcPageHandler.getTransitionalPage(_root); 282 Map<String, String> attributes = transitionalPageName.get(name); 283 String title = attributes.get(UGCPageHandler.ATTRIBUTE_TRANSITIONAL_PAGE_TITLE); 284 String metadataValue = attributes.get(UGCPageHandler.ATTRIBUTE_TRANSITIONAL_PAGE_METADATA_VALUE); 285 return new UGCTransitionalPage(_root, title, metadataValue, name, _resolver, _ugcPageHandler, _skinsManager, _pageDataTypeExtensionPoint, _zoneDataTypeExtensionPoint, _serviceExtensionPoint, _zoneItemDataTypeExtensionPoint); 286 } 287 else 288 { 289 return _root; 290 } 291 } 292 293 @Override 294 public String getParentPath() throws AmetysRepositoryException 295 { 296 if (!_path.equals("_root")) 297 { 298 return _root.getPath() + "/" + _path; 299 } 300 else 301 { 302 return _root.getPath(); 303 } 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 AmetysObjectIterable< ? extends Page> getChildrenPages(boolean includeInvisiblePage) throws AmetysRepositoryException 326 { 327 ArrayList<Page> children = new ArrayList<>(); 328 return new CollectionIterable<>(children); 329 } 330 331 @Override 332 public boolean isVisible() throws AmetysRepositoryException 333 { 334 return true; 335 } 336 337 @Override 338 public Page getChildPageAt(int index) throws UnknownAmetysObjectException, AmetysRepositoryException 339 { 340 throw new UnknownAmetysObjectException("There is no child for ugc page"); 341 } 342 343 @Override 344 public Set<String> getAllowedProfilesForAnyConnectedUser() 345 { 346 return Collections.EMPTY_SET; 347 } 348 349 @Override 350 public Set<String> getDeniedProfilesForAnyConnectedUser() 351 { 352 return Collections.EMPTY_SET; 353 } 354 355 @Override 356 public Set<String> getAllowedProfilesForAnonymous() 357 { 358 return Collections.EMPTY_SET; 359 } 360 361 @Override 362 public Set<String> getDeniedProfilesForAnonymous() 363 { 364 return Collections.EMPTY_SET; 365 } 366 367 @Override 368 public Set<String> getAllowedProfilesForUser(UserIdentity user) 369 { 370 return Collections.EMPTY_SET; 371 } 372 373 @Override 374 public Map<UserIdentity, Set<String>> getAllowedProfilesForUsers() 375 { 376 return Collections.EMPTY_MAP; 377 } 378 379 @Override 380 public Set<UserIdentity> getAllowedUsers(String profileId) 381 { 382 return Collections.EMPTY_SET; 383 } 384 385 @Override 386 public Map<GroupIdentity, Set<String>> getAllowedProfilesForGroups() 387 { 388 return Collections.EMPTY_MAP; 389 } 390 391 @Override 392 public Set<GroupIdentity> getAllowedGroups(String profileId) 393 { 394 return Collections.EMPTY_SET; 395 } 396 397 @Override 398 public Set<String> getDeniedProfilesForUser(UserIdentity user) 399 { 400 return Collections.EMPTY_SET; 401 } 402 403 @Override 404 public Map<UserIdentity, Set<String>> getDeniedProfilesForUsers() 405 { 406 return Collections.EMPTY_MAP; 407 } 408 409 @Override 410 public Set<UserIdentity> getDeniedUsers(String profileId) 411 { 412 return Collections.EMPTY_SET; 413 } 414 415 @Override 416 public Map<GroupIdentity, Set<String>> getDeniedProfilesForGroups() 417 { 418 return Collections.EMPTY_MAP; 419 } 420 421 @Override 422 public Set<GroupIdentity> getDeniedGroups(String profileId) 423 { 424 return Collections.EMPTY_SET; 425 } 426 427 @Override 428 public boolean isInheritanceDisallowed() 429 { 430 return false; 431 } 432 433 public ModelAwareDataHolder getTemplateParametersHolder() throws AmetysRepositoryException 434 { 435 return null; 436 } 437}