001/* 002 * Copyright 2020 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.web.parameters.view; 017 018import java.util.Collection; 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.LinkedList; 022import java.util.List; 023import java.util.Map; 024import java.util.Optional; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.commons.lang.StringUtils; 031import org.apache.commons.lang3.RegExUtils; 032import org.apache.jackrabbit.util.Text; 033 034import org.ametys.cms.contenttype.ContentType; 035import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 036import org.ametys.cms.contenttype.ContentTypesHelper; 037import org.ametys.cms.data.holder.DataHolderRelativeDisableCondition; 038import org.ametys.cms.data.holder.DataHolderRelativeDisableConditions; 039import org.ametys.cms.data.holder.DataHolderRelativeDisableConditionsHelper; 040import org.ametys.cms.data.holder.impl.DefaultModifiableModelAwareDataHolder; 041import org.ametys.cms.repository.Content; 042import org.ametys.plugins.repository.AmetysObject; 043import org.ametys.plugins.repository.AmetysObjectResolver; 044import org.ametys.plugins.repository.RepositoryConstants; 045import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 046import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder; 047import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData; 048import org.ametys.plugins.repository.model.RepeaterDefinition; 049import org.ametys.runtime.i18n.I18nizableText; 050import org.ametys.runtime.model.DefaultElementDefinition; 051import org.ametys.runtime.model.ElementDefinition; 052import org.ametys.runtime.model.Enumerator; 053import org.ametys.runtime.model.Model; 054import org.ametys.runtime.model.ModelItem; 055import org.ametys.runtime.model.StaticEnumerator; 056import org.ametys.runtime.model.View; 057import org.ametys.runtime.model.ViewElement; 058import org.ametys.runtime.model.ViewItem; 059import org.ametys.runtime.model.ViewItemContainer; 060import org.ametys.runtime.model.disableconditions.DisableCondition; 061import org.ametys.runtime.model.disableconditions.DisableCondition.OPERATOR; 062import org.ametys.runtime.model.disableconditions.DisableConditions; 063import org.ametys.runtime.model.type.ModelItemTypeConstants; 064import org.ametys.runtime.parameter.DefaultValidator; 065import org.ametys.runtime.plugin.component.AbstractLogEnabled; 066import org.ametys.web.contenttype.SkinContentViewHelper; 067import org.ametys.web.contenttype.SkinContentViewHelper.SkinContentView; 068import org.ametys.web.data.type.ModelItemTypeExtensionPoint; 069import org.ametys.web.parameters.view.GlobalViewParametersManager.ViewParametersType; 070import org.ametys.web.repository.page.ModifiableZoneItem; 071import org.ametys.web.repository.page.Page; 072import org.ametys.web.repository.page.Page.PageType; 073import org.ametys.web.repository.page.SitemapElement; 074import org.ametys.web.repository.page.Zone; 075import org.ametys.web.repository.page.ZoneItem; 076import org.ametys.web.repository.page.ZoneItem.ZoneType; 077import org.ametys.web.service.Service; 078import org.ametys.web.service.ServiceExtensionPoint; 079import org.ametys.web.skin.Skin; 080import org.ametys.web.skin.SkinTemplate; 081import org.ametys.web.skin.SkinTemplateZone; 082import org.ametys.web.skin.SkinsManager; 083 084/** 085 * Manager for view parameters 086 */ 087public class ViewParametersManager extends AbstractLogEnabled implements Component, Serviceable 088{ 089 /** Avalon Role */ 090 public static final String ROLE = ViewParametersManager.class.getName(); 091 092 /** 093 * The name of the model item to disable inheritance for template 094 * This model item is created from scratch, the name doesn't matter 095 * */ 096 public static final String TEMPLATE_INHERIT_MODEL_ITEM_NAME = "template-inheritance"; 097 098 /** 099 * The name of the model item to disable inheritance for zone 100 * This model item is created from scratch, the name doesn't matter 101 * */ 102 public static final String ZONE_INHERIT_MODEL_ITEM_NAME = "zone-inheritance"; 103 104 /** 105 * The name of the model item containing the content view parameters 106 * This model item is created from scratch, the name doesn't matter 107 * */ 108 public static final String CONTENT_VIEW_MODEL_ITEM_NAME = "content-views"; 109 110 /** 111 * The name of default attribute in the service parameters to set the service view 112 * Warning : it's a convention to call this parameter 'xslt', but a service can't have several view xsl with different names 113 * */ 114 public static final String SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME = "xslt"; 115 116 /** The name of the tag containing the template view parameters */ 117 public static final String VIEW_PARAMETERS_TEMPLATE_CONF_NAME = "parameters"; 118 119 /** The name of the tag containing the zone view parameters */ 120 public static final String VIEW_PARAMETERS_ZONE_CONF_NAME = "parameters"; 121 122 /** The name of the parent tag containing the zone item view parameters */ 123 public static final String VIEW_PARAMETERS_ZONE_ITEM_PARENT_CONF_NAME = "zone-items"; 124 125 /** The name of the tag containing the zone item view parameters */ 126 public static final String VIEW_PARAMETERS_ZONE_ITEM_CONF_NAME = "parameters"; 127 128 /** The name of the tag containing the service view parameters */ 129 public static final String VIEW_PARAMETERS_SERVICE_CONF_NAME = "parameters"; 130 131 /** The name of the tag containing the content view parameters */ 132 public static final String VIEW_PARAMETERS_CONTENT_CONF_NAME = "parameters"; 133 134 /** The composite name for view parameters */ 135 public static final String VIEW_PARAMETERS_COMPOSITE_NAME = "view_parameters"; 136 137 /** The composite name for content view parameters */ 138 public static final String CONTENT_VIEW_PARAMETERS_COMPOSITE_NAME = "content_view_parameters"; 139 140 /** The composite name for service view parameters */ 141 public static final String SERVICE_VIEW_PARAMETERS_COMPOSITE_NAME = "service_view_parameters"; 142 143 /** The node type for view parameters */ 144 public static final String VIEW_PARAMETERS_NODETYPE = RepositoryConstants.NAMESPACE_PREFIX + ":compositeMetadata"; 145 146 /** The Ametys object resolver */ 147 protected AmetysObjectResolver _resolver; 148 149 /** The skins manager */ 150 protected SkinsManager _skinsManager; 151 152 /** Helper for skin views */ 153 protected SkinContentViewHelper _skinContentViewHelper; 154 155 /** The service view parameters manager */ 156 protected ServiceViewParametersManager _serviceViewParametersManager; 157 158 /** The content view parameters manager */ 159 protected ContentViewParametersManager _contentViewParametersManager; 160 161 /** The global view parameters manager */ 162 protected GlobalViewParametersManager _globalViewParametersManager; 163 164 /** The content types helper */ 165 protected ContentTypesHelper _contentTypesHelper; 166 167 /** The content type extension point */ 168 protected ContentTypeExtensionPoint _contentTypeEP; 169 170 /** The view parameters type extension point */ 171 protected ModelItemTypeExtensionPoint _viewParametersTypeEP; 172 173 /** The service extension point */ 174 protected ServiceExtensionPoint _serviceEP; 175 176 /** The data holder relative disable condition helper */ 177 protected DataHolderRelativeDisableConditionsHelper _disableConditionsHelper; 178 179 public void service(ServiceManager manager) throws ServiceException 180 { 181 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 182 _skinsManager = (SkinsManager) manager.lookup(SkinsManager.ROLE); 183 _skinContentViewHelper = (SkinContentViewHelper) manager.lookup(SkinContentViewHelper.ROLE); 184 _serviceViewParametersManager = (ServiceViewParametersManager) manager.lookup(ServiceViewParametersManager.ROLE); 185 _contentViewParametersManager = (ContentViewParametersManager) manager.lookup(ContentViewParametersManager.ROLE); 186 _globalViewParametersManager = (GlobalViewParametersManager) manager.lookup(GlobalViewParametersManager.ROLE); 187 _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 188 _contentTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 189 _viewParametersTypeEP = (ModelItemTypeExtensionPoint) manager.lookup(ModelItemTypeExtensionPoint.ROLE_VIEW_PARAM); 190 _serviceEP = (ServiceExtensionPoint) manager.lookup(ServiceExtensionPoint.ROLE); 191 _disableConditionsHelper = (DataHolderRelativeDisableConditionsHelper) manager.lookup(DataHolderRelativeDisableConditionsHelper.ROLE); 192 } 193 194 /** 195 * Get the view parameters holder 196 * @param parentJCRData the parent JCR data 197 * @param viewParametersModel the view parameters model 198 * @return the view parameters holder 199 */ 200 public ModifiableModelAwareDataHolder getParametersHolder(JCRRepositoryData parentJCRData, ViewParametersModel viewParametersModel) 201 { 202 JCRRepositoryData viewRepositoryData = _getJCRRepositoryData(parentJCRData, VIEW_PARAMETERS_COMPOSITE_NAME); 203 return new DefaultModifiableModelAwareDataHolder(viewRepositoryData, viewParametersModel); 204 } 205 206 /** 207 * Get the content view parameters holder 208 * @param parentJCRData the parent JCR data 209 * @param viewName the view name 210 * @param viewParametersModel the view parameters model 211 * @return the view parameters holder 212 */ 213 public ModifiableModelAwareDataHolder getContentViewParametersHolder(JCRRepositoryData parentJCRData, String viewName, ViewParametersModel viewParametersModel) 214 { 215 JCRRepositoryData viewParametersRepositoryData = _getJCRRepositoryData(parentJCRData, CONTENT_VIEW_PARAMETERS_COMPOSITE_NAME); 216 JCRRepositoryData viewRepositoryData = _getJCRRepositoryData(viewParametersRepositoryData, viewName); 217 218 return new DefaultModifiableModelAwareDataHolder(viewRepositoryData, viewParametersModel); 219 } 220 221 /** 222 * Get the service view parameters holder 223 * @param parentJCRData the parent JCR data 224 * @param viewName the view name 225 * @param viewParametersModel the view parameters model 226 * @return the view parameters holder 227 */ 228 public ModifiableModelAwareDataHolder getServiceViewParametersHolder(JCRRepositoryData parentJCRData, String viewName, ViewParametersModel viewParametersModel) 229 { 230 JCRRepositoryData viewParametersRepositoryData = _getJCRRepositoryData(parentJCRData, SERVICE_VIEW_PARAMETERS_COMPOSITE_NAME); 231 JCRRepositoryData xsltRepositoryData = _getJCRRepositoryData(viewParametersRepositoryData, SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME); 232 JCRRepositoryData viewRepositoryData = _getJCRRepositoryData(xsltRepositoryData, Text.escapeIllegalJcrChars(viewName)); 233 234 return new DefaultModifiableModelAwareDataHolder(viewRepositoryData, viewParametersModel); 235 } 236 237 private JCRRepositoryData _getJCRRepositoryData(JCRRepositoryData parentJCRData, String jcrName) 238 { 239 JCRRepositoryData jcrData = null; 240 if (parentJCRData.hasValue(jcrName)) 241 { 242 jcrData = (JCRRepositoryData) parentJCRData.getRepositoryData(jcrName); 243 } 244 else 245 { 246 jcrData = (JCRRepositoryData) parentJCRData.addRepositoryData(jcrName, VIEW_PARAMETERS_NODETYPE); 247 } 248 249 return jcrData; 250 } 251 252 /** 253 * Get the template view parameters model 254 * @param skinId the skin id 255 * @param templateId the template id 256 * @return the view parameters 257 */ 258 public Optional<ViewParametersModel> getTemplateViewParametersModel(String skinId, String templateId) 259 { 260 Skin skin = _skinsManager.getSkin(skinId); 261 SkinTemplate skinTemplate = skin.getTemplate(templateId); 262 return skinTemplate != null ? getTemplateViewParametersModel(skinTemplate) : Optional.empty(); 263 } 264 265 /** 266 * Get the template view parameters model 267 * @param skinTemplate the skin template 268 * @return the view parameters 269 */ 270 public Optional<ViewParametersModel> getTemplateViewParametersModel(SkinTemplate skinTemplate) 271 { 272 Optional<ViewParametersModel> optionalViewParameters = skinTemplate.getViewParameters(); 273 if (optionalViewParameters.isPresent()) 274 { 275 ViewParametersModel viewParameters = optionalViewParameters.get(); 276 if (viewParameters.isNotEmpty()) 277 { 278 ViewParameter<Boolean> inheritCheckboxElement = getInheritCheckboxElement(viewParameters, TEMPLATE_INHERIT_MODEL_ITEM_NAME); 279 viewParameters.addModelItem(inheritCheckboxElement); 280 } 281 } 282 283 return optionalViewParameters; 284 } 285 286 /** 287 * Get the zone view parameters model 288 * @param skinId the skin id 289 * @param templateId the template id 290 * @param zoneId the zone id 291 * @return the view parameters 292 */ 293 public Optional<ViewParametersModel> getZoneViewParametersModel(String skinId, String templateId, String zoneId) 294 { 295 Skin skin = _skinsManager.getSkin(skinId); 296 SkinTemplate skinTemplate = skin.getTemplate(templateId); 297 if (skinTemplate == null) 298 { 299 return Optional.empty(); 300 } 301 302 SkinTemplateZone skinTemplateZone = skinTemplate.getZone(zoneId); 303 return skinTemplateZone != null ? getZoneViewParametersModel(skinTemplateZone) : Optional.empty(); 304 } 305 306 /** 307 * Get the zone view parameters model 308 * @param skinTemplateZone the skin template zone 309 * @return the view parameters 310 */ 311 public Optional<ViewParametersModel> getZoneViewParametersModel(SkinTemplateZone skinTemplateZone) 312 { 313 Optional<ViewParametersModel> optionalViewParameters = skinTemplateZone.getViewParameters(); 314 if (optionalViewParameters.isPresent()) 315 { 316 ViewParametersModel viewParameters = optionalViewParameters.get(); 317 if (viewParameters.isNotEmpty()) 318 { 319 ViewParameter<Boolean> inheritCheckboxElement = getInheritCheckboxElement(viewParameters, ZONE_INHERIT_MODEL_ITEM_NAME); 320 viewParameters.addModelItem(inheritCheckboxElement); 321 } 322 } 323 324 return optionalViewParameters; 325 } 326 327 /** 328 * Get the zone item view parameters model 329 * @param zoneItem the zone item 330 * @return the view parameters 331 */ 332 public Optional<ViewParametersModel> getZoneItemViewParametersModel(ZoneItem zoneItem) 333 { 334 Zone zone = zoneItem.getZone(); 335 SitemapElement sitemapElement = zone.getSitemapElement(); 336 337 return getZoneItemViewParametersModel(sitemapElement.getSite().getSkinId(), sitemapElement.getTemplate(), zone.getName()); 338 } 339 340 /** 341 * Get the zone item view parameters model 342 * @param skinId the skin id 343 * @param templateId the template id 344 * @param zoneName the zone name 345 * @return the view parameters 346 */ 347 public Optional<ViewParametersModel> getZoneItemViewParametersModel(String skinId, String templateId, String zoneName) 348 { 349 Skin skin = _skinsManager.getSkin(skinId); 350 SkinTemplate skinTemplate = skin.getTemplate(templateId); 351 if (skinTemplate == null) 352 { 353 return Optional.empty(); 354 } 355 356 SkinTemplateZone skinTemplateZone = skinTemplate.getZone(zoneName); 357 return skinTemplateZone != null ? skinTemplateZone.getZoneItemViewParameters() : Optional.empty(); 358 } 359 360 /** 361 * Get the content view parameters model 362 * @param zoneItem the zone item 363 * @return the view parameters 364 */ 365 public Optional<ViewParametersModel> getContentViewParametersModel(ZoneItem zoneItem) 366 { 367 if (zoneItem.getType() == ZoneType.CONTENT) 368 { 369 String viewName = zoneItem.getViewName(); 370 Content content = zoneItem.getContent(); 371 String skinId = zoneItem.getZone().getSitemapElement().getSite().getSkinId(); 372 373 return getContentViewParametersModel(skinId, content, viewName); 374 } 375 else 376 { 377 throw new IllegalArgumentException("Can't get content view parameters model from a none content zone item"); 378 } 379 } 380 381 /** 382 * Get the content view parameters model 383 * @param skinId the skin id 384 * @param content the content 385 * @param viewName the view name 386 * @return the view parameters 387 */ 388 public Optional<ViewParametersModel> getContentViewParametersModel(String skinId, Content content, String viewName) 389 { 390 String contentTypeIdForRendering = _contentTypesHelper.getContentTypeIdForRendering(content); 391 return _contentViewParametersManager.getViewParameters(skinId, contentTypeIdForRendering, viewName); 392 } 393 394 /** 395 * Get all view parameters model for one content 396 * @param skinId the skin id 397 * @param content the content 398 * @return the map of view parameters model (with the view name) 399 */ 400 public Map<String, ViewParametersModel> getContentViewParametersModels(String skinId, Content content) 401 { 402 Map<String, ViewParametersModel> viewParametersModels = new HashMap<>(); 403 String contentTypeIdForRendering = _contentTypesHelper.getContentTypeIdForRendering(content); 404 if (_contentTypeEP.hasExtension(contentTypeIdForRendering)) 405 { 406 ContentType contentType = _contentTypeEP.getExtension(contentTypeIdForRendering); 407 for (String viewName : contentType.getViewNames(false)) 408 { 409 Optional<ViewParametersModel> contentViewParameters = getContentViewParametersModel(skinId, content, viewName); 410 if (contentViewParameters.isPresent()) 411 { 412 viewParametersModels.put(viewName, contentViewParameters.get()); 413 } 414 } 415 416 for (SkinContentView skinContentView : _skinContentViewHelper.getContentViewsFromSkin(skinId, contentType)) 417 { 418 String viewName = skinContentView.name(); 419 Optional<ViewParametersModel> contentViewParameters = getContentViewParametersModel(skinId, content, viewName); 420 if (contentViewParameters.isPresent()) 421 { 422 viewParametersModels.put(viewName, contentViewParameters.get()); 423 } 424 } 425 } 426 return viewParametersModels; 427 } 428 429 /** 430 * Get a static enumerator with all content view 431 * @param skinId the skin id 432 * @param content the content 433 * @return the element definition of the enumerator 434 */ 435 public ElementDefinition<String> getContentViewEnumerator(String skinId, Content content) 436 { 437 ElementDefinition<String> elementDef = new DefaultElementDefinition<>(); 438 439 String contentTypeIdForRendering = _contentTypesHelper.getContentTypeIdForRendering(content); 440 ContentType contentType = _contentTypeEP.getExtension(contentTypeIdForRendering); 441 442 StaticEnumerator<String> enumerator = new StaticEnumerator<>(); 443 for (String viewName : contentType.getViewNames(false)) 444 { 445 View view = contentType.getView(viewName); 446 enumerator.add(view.getLabel(), viewName); 447 } 448 449 for (SkinContentView skinContentView : _skinContentViewHelper.getContentViewsFromSkin(skinId, contentType)) 450 { 451 enumerator.add(skinContentView.label(), skinContentView.name()); 452 } 453 454 elementDef.setName(CONTENT_VIEW_MODEL_ITEM_NAME); 455 elementDef.setLabel(new I18nizableText("plugin.web", "PLUGINS_WEB_VIEW_PARAMETERS_DIALOG_BOX_CONTENT_VIEW_FIELD_LABEL")); 456 elementDef.setEnumerator(enumerator); 457 elementDef.setType(_viewParametersTypeEP.getExtension(ModelItemTypeConstants.STRING_TYPE_ID)); 458 elementDef.setMultiple(false); 459 elementDef.setValidator(new DefaultValidator(null, true)); 460 461 return elementDef; 462 } 463 464 /** 465 * Copy content view parameters of the source zone item to the destination zone item 466 * @param zoneItemSource the source zone item 467 * @param zoneItemDestination the destination zone item 468 */ 469 public void copyContentViewParameters(ModifiableZoneItem zoneItemSource, ModifiableZoneItem zoneItemDestination) 470 { 471 Content content = zoneItemSource.getContent(); 472 473 String contentTypeIdForRendering = _contentTypesHelper.getContentTypeIdForRendering(content); 474 ContentType contentType = _contentTypeEP.getExtension(contentTypeIdForRendering); 475 476 for (String viewName : contentType.getViewNames(false)) 477 { 478 zoneItemSource.getContentViewParametersHolder(viewName).copyTo(zoneItemDestination.getContentViewParametersHolder(viewName)); 479 } 480 481 String skinId = zoneItemSource.getZone() 482 .getSitemapElement() 483 .getSite() 484 .getSkinId(); 485 for (SkinContentView skinContentView : _skinContentViewHelper.getContentViewsFromSkin(skinId, contentType)) 486 { 487 String viewName = skinContentView.name(); 488 zoneItemSource.getContentViewParametersHolder(viewName).copyTo(zoneItemDestination.getContentViewParametersHolder(viewName)); 489 } 490 } 491 492 /** 493 * Get the service view parameters model 494 * @param zoneItem the zone item 495 * @return the view parameters 496 */ 497 public Optional<ViewParametersModel> getServiceViewParametersModel(ZoneItem zoneItem) 498 { 499 if (zoneItem.getType() == ZoneType.SERVICE) 500 { 501 ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters(); 502 if (serviceParameters.hasDefinition(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME)) 503 { 504 String viewName = serviceParameters.getValue(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME); 505 String serviceId = zoneItem.getServiceId(); 506 String skinId = zoneItem.getZone().getSitemapElement().getSite().getSkinId(); 507 508 return getServiceViewParametersModel(skinId, serviceId, viewName); 509 } 510 } 511 else 512 { 513 throw new IllegalArgumentException("Can't get service view parameters model from a none service zone item"); 514 } 515 516 return Optional.empty(); 517 } 518 519 /** 520 * Get the service view parameters model 521 * @param skinId the skin id 522 * @param serviceId the service id 523 * @param viewName the view name 524 * @return the view parameters 525 */ 526 public Optional<ViewParametersModel> getServiceViewParametersModel(String skinId, String serviceId, String viewName) 527 { 528 return _serviceViewParametersManager.getViewParameters(skinId, serviceId, viewName); 529 } 530 531 /** 532 * Get all view parameters model for one service 533 * @param skinId the skin id 534 * @param serviceId the service id 535 * @return the map of view parameters model (with the view name) 536 */ 537 public Map<String, ViewParametersModel> getServiceViewParametersModels(String skinId, String serviceId) 538 { 539 Map<String, ViewParametersModel> viewParametersModels = new HashMap<>(); 540 541 ElementDefinition<String> serviceViewEnumerator = getServiceViewEnumerator(serviceId); 542 if (serviceViewEnumerator != null) 543 { 544 Enumerator<String> enumerator = serviceViewEnumerator.getEnumerator(); 545 try 546 { 547 for (String viewName : enumerator.getEntries().keySet()) 548 { 549 Optional<ViewParametersModel> serviceViewParameters = getServiceViewParametersModel(skinId, serviceId, viewName); 550 if (serviceViewParameters.isPresent()) 551 { 552 viewParametersModels.put(viewName, serviceViewParameters.get()); 553 } 554 } 555 } 556 catch (Exception e) 557 { 558 getLogger().error("Can't get view list for service '{}'", serviceId, e); 559 } 560 } 561 562 return viewParametersModels; 563 } 564 565 /** 566 * Get a service enumerator with all content view 567 * @param serviceId the service id 568 * @return the element definition of the enumerator 569 */ 570 @SuppressWarnings("unchecked") 571 public ElementDefinition<String> getServiceViewEnumerator(String serviceId) 572 { 573 Service service = _serviceEP.getExtension(serviceId); 574 575 Map<String, ModelItem> parameters = service.getParameters(); 576 if (parameters.containsKey(SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME)) 577 { 578 ElementDefinition<String> xsltDefinition = (ElementDefinition<String>) parameters.get(SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME); 579 return xsltDefinition; 580 } 581 582 return null; 583 } 584 585 /** 586 * Copy service view parameters of the source zone item to the destination zone item 587 * @param zoneItemSource the source zone item 588 * @param zoneItemDestination the destination zone item 589 */ 590 public void copyServiceViewParameters(ModifiableZoneItem zoneItemSource, ModifiableZoneItem zoneItemDestination) 591 { 592 String serviceId = zoneItemSource.getServiceId(); 593 594 ElementDefinition<String> serviceViewEnumerator = getServiceViewEnumerator(serviceId); 595 if (serviceViewEnumerator != null) 596 { 597 Enumerator<String> enumerator = serviceViewEnumerator.getEnumerator(); 598 try 599 { 600 for (String viewName : enumerator.getEntries().keySet()) 601 { 602 zoneItemSource.getServiceViewParametersHolder(viewName).copyTo(zoneItemDestination.getServiceViewParametersHolder(viewName)); 603 } 604 } 605 catch (Exception e) 606 { 607 getLogger().error("Can't get view list for service '{}'. So it can't copy the service view parameters", serviceId, e); 608 } 609 } 610 } 611 612 /** 613 * Normalize the view name (for service view value with /) 614 * @param viewName the view name 615 * @return the normalized view name 616 */ 617 public String normalizeViewName(String viewName) 618 { 619 return RegExUtils.replaceAll(viewName, "/", "\\$"); 620 } 621 622 /** 623 * Add model items to the view item container and add prefix to items name 624 * @param modelItems the model items 625 * @param prefix the prefix 626 * @param viewItemContainer the view item container 627 * @return the list of included model items 628 */ 629 public List<ModelItem> includeModelItems(Collection<? extends ModelItem> modelItems, String prefix, ViewItemContainer viewItemContainer) 630 { 631 return includeModelItems(modelItems, prefix, viewItemContainer, Optional.empty()); 632 } 633 634 /** 635 * Add model items to the view item container and add prefix to items name 636 * @param modelItems the model items 637 * @param prefix the prefix 638 * @param viewItemContainer the view item container 639 * @param index index at which the model items have to be included 640 * @return the list of included model items 641 */ 642 public List<ModelItem> includeModelItems(Collection<? extends ModelItem> modelItems, String prefix, ViewItemContainer viewItemContainer, Optional<Integer> index) 643 { 644 List<ModelItem> copiedModelItems = new LinkedList<>(); 645 int i = index.orElse(viewItemContainer.getViewItems().size()); 646 for (ModelItem modelItem : modelItems) 647 { 648 if (modelItem instanceof ElementDefinition) 649 { 650 @SuppressWarnings("unchecked") 651 ElementDefinition modelItemCopy = new DefaultElementDefinition((ElementDefinition) modelItem); 652 modelItemCopy.setDisableConditions(null); 653 modelItemCopy.setName(prefix + modelItem.getName()); 654 655 ViewElement viewElement = new ViewElement(); 656 viewElement.setDefinition(modelItemCopy); 657 658 viewItemContainer.insertViewItem(viewElement, i); 659 i++; // increase the index in order to include the next item after this one 660 661 copiedModelItems.add(modelItemCopy); 662 } 663 } 664 665 return copiedModelItems; 666 } 667 668 /** 669 * Set the a disable condition to all model items. These model items will show if the value of the element (elementName) equal the condition value (conditionValue) 670 * @param elementName the element name 671 * @param operator the operator 672 * @param conditionValue the condition value 673 * @param modelItems the list of model items 674 */ 675 public void setDisableConditions(String elementName, OPERATOR operator, String conditionValue, Collection< ? extends ModelItem> modelItems) 676 { 677 for (ModelItem modelItem : modelItems) 678 { 679 if (modelItem instanceof ElementDefinition) 680 { 681 DisableConditions disableConditions = new DataHolderRelativeDisableConditions(); 682 DisableCondition condition = new DataHolderRelativeDisableCondition(elementName, operator, conditionValue, _disableConditionsHelper); 683 disableConditions.getConditions().add(condition); 684 modelItem.setDisableConditions(disableConditions); 685 } 686 else if (modelItem instanceof RepeaterDefinition) 687 { 688 // Actually we don't handle repeater 689 } 690 } 691 } 692 693 /** 694 * Get a check box to override inherit parameters 695 * @param model the model of the element 696 * @param name the name of the check box 697 * @return the element definition of the enumerator 698 */ 699 public ViewParameter<Boolean> getInheritCheckboxElement(Model model, String name) 700 { 701 ViewParameter<Boolean> elementDef = new ViewParameter<>(); 702 703 elementDef.setName(name); 704 elementDef.setLabel(new I18nizableText("plugin.web", "PLUGINS_WEB_VIEW_PARAMETERS_INHERITANCE_CHECKBOX_LABEL")); 705 elementDef.setDescription(new I18nizableText("plugin.web", "PLUGINS_WEB_VIEW_PARAMETERS_INHERITANCE_CHECKBOX_DESC")); 706 elementDef.setType(_viewParametersTypeEP.getExtension(ModelItemTypeConstants.BOOLEAN_TYPE_ID)); 707 elementDef.setMultiple(false); 708 elementDef.setDefaultValue(false); 709 elementDef.setModel(model); 710 elementDef.setInheritances(null); 711 712 return elementDef; 713 } 714 715 /** 716 * Get the global view parameters for the given type and add the view parameters to it 717 * @param skinId the skin id 718 * @param type the type 719 * @param viewParameters the view parameters 720 * @return the new view parameters (with global view parameters) 721 */ 722 public Optional<ViewParametersModel> addGlobalViewParameters(String skinId, ViewParametersType type, Optional<ViewParametersModel> viewParameters) 723 { 724 Optional<ViewParametersModel> globalViewParameters = _globalViewParametersManager.getViewParameters(skinId, type); 725 if (globalViewParameters.isEmpty() || !globalViewParameters.get().isNotEmpty()) 726 { 727 return viewParameters; 728 } 729 730 if (viewParameters.isEmpty()) 731 { 732 return globalViewParameters; 733 } 734 735 ViewParametersModel newViewParameters = new ViewParametersModel(viewParameters.get().getId(), new View(), new LinkedHashMap<>()); 736 View newView = newViewParameters.getView(); 737 738 // Add global view parameters 739 _addViewItems(globalViewParameters.get().getView(), newView); 740 _addParameters(globalViewParameters.get().getModelItems(), newViewParameters); 741 742 // Add view parameters 743 _addViewItems(viewParameters.get().getView(), newView); 744 _addParameters(viewParameters.get().getModelItems(), newViewParameters); 745 746 return Optional.ofNullable(newViewParameters); 747 } 748 749 /** 750 * Get the parameter holder with the effective parameter path for a view parameter of a template, taking into account the inheritance. 751 * The parameter path can be different in case of inheritance. 752 * @param page the page 753 * @param parameterPath the initial parameter path. 754 * @return the {@link ViewParameterHolder} for this page and parameter 755 */ 756 public Optional<ViewParameterHolder> getTemplateViewParameterHolderWithInheritance(Page page, String parameterPath) 757 { 758 Optional<ViewParametersModel> viewParametersModelOptional = getTemplateViewParametersModel(page.getSite().getSkinId(), page.getTemplate()); 759 if (viewParametersModelOptional.isEmpty()) 760 { 761 // No view parameters model 762 return Optional.empty(); 763 } 764 765 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 766 if (!viewParametersModel.hasModelItem(parameterPath)) 767 { 768 // The parameter path doesn't exist in the model 769 return Optional.empty(); 770 } 771 772 ModelItem modelItem = viewParametersModel.getModelItem(parameterPath); 773 return getTemplateViewParameterHolderWithInheritance(page, modelItem); 774 } 775 776 /** 777 * Get the parameter holder with the effective parameter path for a view parameter of a template, taking into account the inheritance. 778 * The parameter path can be different in case of inheritance. 779 * @param page the page 780 * @param modelItem the model item of parameter 781 * @return the {@link ViewParameterHolder} for this page and parameter 782 */ 783 public Optional<ViewParameterHolder> getTemplateViewParameterHolderWithInheritance(Page page, ModelItem modelItem) 784 { 785 ModelAwareDataHolder dataHolder = page.getTemplateParametersHolder(); 786 787 if (!(modelItem instanceof ViewParameter)) 788 { 789 return _getViewParamaterHolder(dataHolder, modelItem.getPath()); 790 } 791 792 ViewParameter viewParameter = (ViewParameter) modelItem; 793 794 boolean overrideInherit = dataHolder != null ? dataHolder.getValue(ViewParametersManager.TEMPLATE_INHERIT_MODEL_ITEM_NAME, false, false) : false; 795 if (!viewParameter.hasInheritances() || overrideInherit) 796 { 797 // The param has no inheritance or the override inherit param is checked, so just take the value 798 return _getViewParamaterHolder(dataHolder, modelItem.getPath()); 799 } 800 else if (viewParameter.hasInheritances()) 801 { 802 return _getTemplateViewParameterHolderWithInheritance(page, viewParameter, modelItem.getPath()); 803 } 804 805 // No value found 806 return Optional.empty(); 807 } 808 809 /** 810 * Get the parameter holder with the effective parameter path for a view parameter of a template, taking into account the inheritance. 811 * The parameter path can be different in case of inheritance. 812 * @param page the page 813 * @param viewParameter the view parameter 814 * @param parameterPath the parameter path. 815 * @return the {@link ViewParameterHolder} for this page and parameter 816 */ 817 protected Optional<ViewParameterHolder> _getTemplateViewParameterHolderWithInheritance(Page page, ViewParameter viewParameter, String parameterPath) 818 { 819 AmetysObject parent = page.getParent(); 820 if (!(parent instanceof Page)) 821 { 822 // No parent page 823 return Optional.empty(); 824 } 825 826 Page parentPage = (Page) parent; 827 if (parentPage.getType() != PageType.CONTAINER) 828 { 829 // Just ignore blank page or page with redirection 830 return _getTemplateViewParameterHolderWithInheritance(parentPage, viewParameter, parameterPath); 831 } 832 833 // Parameter has defined inheritance 834 String parentTemplate = parentPage.getTemplate(); 835 Map<String, String> inheritances = viewParameter.getInheritances(); 836 boolean isTemplateMatch = false; 837 for (String template : inheritances.keySet()) 838 { 839 // All template match || The parent page match 840 if (template == null || parentTemplate.equals(template)) 841 { 842 String context = inheritances.get(template); 843 if (context != null) // if null, it means the template is excluded from inheritance 844 { 845 isTemplateMatch = true; 846 String inheritModelItemPath = "*".equals(context) ? viewParameter.getName() : context; 847 Optional<ViewParameterHolder> templateParameterHolder = getTemplateViewParameterHolderWithInheritance(parentPage, inheritModelItemPath); 848 if (templateParameterHolder.isPresent()) 849 { 850 return templateParameterHolder; 851 } 852 } 853 } 854 } 855 856 if (!isTemplateMatch) 857 { 858 // No template match inheritance, so just take the holder and the path 859 return _getViewParamaterHolder(page.getTemplateParametersHolder(), parameterPath); 860 861 } 862 863 return Optional.empty(); 864 } 865 866 /** 867 * Get the parameter holder with the effective parameter path for a view parameter of a zone, taking into account the inheritance. 868 * The parameter path can be different in case of inheritance. 869 * @param page the page 870 * @param zone the zone 871 * @param parameterPath the initial parameter path. 872 * @return the {@link ViewParameterHolder} for this page, zone and parameter 873 */ 874 public Optional<ViewParameterHolder> getZoneViewParameterHolderWithInheritance(Page page, Zone zone, String parameterPath) 875 { 876 Optional<ViewParametersModel> viewParametersModelOptional = getZoneViewParametersModel(page.getSite().getSkinId(), page.getTemplate(), zone.getName()); 877 if (viewParametersModelOptional.isEmpty()) 878 { 879 // No view parameters model 880 return Optional.empty(); 881 } 882 883 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 884 if (!viewParametersModel.hasModelItem(parameterPath)) 885 { 886 // The parameter path doesn't exist in the model 887 return Optional.empty(); 888 } 889 890 ModelItem modelItem = viewParametersModel.getModelItem(parameterPath); 891 return getZoneViewParameterHolderWithInheritance(page, zone, modelItem); 892 } 893 894 /** 895 * Get the parameter holder with the effective parameter path for a view parameter of a zone, taking into account the inheritance. 896 * The parameter path can be different in case of inheritance. 897 * @param page the page 898 * @param zone the zone 899 * @param modelItem the model item of the parameter 900 * @return the {@link ViewParameterHolder} for this page, zone and parameter 901 */ 902 public Optional<ViewParameterHolder> getZoneViewParameterHolderWithInheritance(Page page, Zone zone, ModelItem modelItem) 903 { 904 ModelAwareDataHolder dataHolder = zone.getZoneParametersHolder(); 905 906 if (!(modelItem instanceof ViewParameter)) 907 { 908 return _getViewParamaterHolder(dataHolder, modelItem.getPath()); 909 } 910 911 ViewParameter viewParameter = (ViewParameter) modelItem; 912 boolean overrideInherit = dataHolder != null ? dataHolder.getValue(ViewParametersManager.ZONE_INHERIT_MODEL_ITEM_NAME, false, false) : false; 913 if (!viewParameter.hasInheritances() || overrideInherit) 914 { 915 // The param has no inheritance or the override inherit param is checked, so just take the value 916 return _getViewParamaterHolder(dataHolder, modelItem.getPath()); 917 } 918 else if (viewParameter.hasInheritances()) 919 { 920 return _getZoneViewParameterHolderWithInheritance(page, zone, viewParameter, modelItem.getPath()); 921 } 922 923 // No value found 924 return Optional.empty(); 925 } 926 927 /** 928 * Get the parameter holder with the effective parameter path for a view parameter of a zone, taking into account the inheritance. 929 * The parameter path can be different in case of inheritance. 930 * @param page the page 931 * @param zone the zone 932 * @param viewParameter the view parameter 933 * @param parameterPath the parameter path. 934 * @return the {@link ViewParameterHolder} for this page, zone and parameter 935 */ 936 protected Optional<ViewParameterHolder> _getZoneViewParameterHolderWithInheritance(Page page, Zone zone, ViewParameter viewParameter, String parameterPath) 937 { 938 AmetysObject parent = page.getParent(); 939 if (!(parent instanceof Page)) 940 { 941 // No parent page 942 return Optional.empty(); 943 } 944 945 Page parentPage = (Page) parent; 946 if (parentPage.getType() != PageType.CONTAINER) 947 { 948 // Just ignore blank page or page with redirection 949 return _getZoneViewParameterHolderWithInheritance(parentPage, zone, viewParameter, parameterPath); 950 } 951 952 // Parameter has defined inheritance 953 String parentTemplate = parentPage.getTemplate(); 954 Map<String, String> inheritances = viewParameter.getInheritances(); 955 boolean isTemplateMatch = false; 956 for (String template : inheritances.keySet()) 957 { 958 // All template match || The parent page match 959 if (template == null || parentTemplate.equals(template)) 960 { 961 String context = inheritances.get(template); 962 if (context != null) // if null, it means the template is excluded from inheritance 963 { 964 isTemplateMatch = true; 965 966 String inheritModelItemPath = viewParameter.getName(); 967 String zoneName = zone.getName(); 968 if (!"*".equals(context)) 969 { 970 zoneName = StringUtils.substringBefore(context, "->"); 971 inheritModelItemPath = StringUtils.substringAfter(context, "->"); 972 } 973 974 if (parentPage.hasZone(zoneName)) 975 { 976 Optional<ViewParameterHolder> zoneParameterHolder = getZoneViewParameterHolderWithInheritance(parentPage, parentPage.getZone(zoneName), inheritModelItemPath); 977 if (zoneParameterHolder.isPresent()) 978 { 979 return zoneParameterHolder; 980 } 981 } 982 } 983 } 984 } 985 986 if (!isTemplateMatch) 987 { 988 // No template match inheritance, so just take the holder and the path 989 return _getViewParamaterHolder(zone.getZoneParametersHolder(), parameterPath); 990 } 991 992 return Optional.empty(); 993 } 994 995 /** 996 * Get content view parameters holder from the zone item 997 * @param zoneItem the zone item 998 * @return the data holder 999 */ 1000 public Optional<ModelAwareDataHolder> getContentViewParametersHolder(ZoneItem zoneItem) 1001 { 1002 if (zoneItem.getType() == ZoneType.CONTENT) 1003 { 1004 String viewName = zoneItem.getViewName(); 1005 return Optional.ofNullable(zoneItem.getContentViewParametersHolder(viewName)); 1006 } 1007 else 1008 { 1009 throw new IllegalArgumentException("Zone item with id '" + zoneItem.getId() + " is not of the expected type 'content' to get the content view parameters"); 1010 } 1011 } 1012 1013 /** 1014 * Get service view parameters holder from the zone item 1015 * @param zoneItem the zone item 1016 * @return the data holder 1017 */ 1018 public Optional<ModelAwareDataHolder> getServiceViewParametersHolder(ZoneItem zoneItem) 1019 { 1020 ModelAwareDataHolder dataHolder = null; 1021 if (zoneItem.getType() == ZoneType.SERVICE) 1022 { 1023 ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters(); 1024 if (serviceParameters.hasDefinition(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME)) 1025 { 1026 String viewName = serviceParameters.getValue(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME, true, null); 1027 dataHolder = zoneItem.getServiceViewParametersHolder(viewName); 1028 } 1029 } 1030 else 1031 { 1032 throw new IllegalArgumentException("Zone item with id '" + zoneItem.getId() + " is not of the expected type 'service' to get the service view parameters"); 1033 } 1034 1035 return Optional.ofNullable(dataHolder); 1036 } 1037 1038 /** 1039 * Get the template parameter value 1040 * @param <T> type of the value to retrieve 1041 * @param page the page 1042 * @param parameterPath the parameter path 1043 * @return the template parameter value. Can be null. 1044 */ 1045 public <T extends Object> T getTemplateParameterValue(Page page, String parameterPath) 1046 { 1047 Optional<ViewParameterHolder> templateViewParameterHolder = getTemplateViewParameterHolderWithInheritance(page, parameterPath); 1048 return templateViewParameterHolder.isPresent() ? templateViewParameterHolder.get().getValue() : null; 1049 } 1050 1051 /** 1052 * Get the zone parameter value 1053 * @param <T> type of the value to retrieve 1054 * @param page the page 1055 * @param zone the zone 1056 * @param parameterPath the parameter path 1057 * @return the zone parameter value. Can be null. 1058 */ 1059 public <T extends Object> T getZoneParameterValue(Page page, Zone zone, String parameterPath) 1060 { 1061 Optional<ViewParameterHolder> zoneViewParameterHolder = getZoneViewParameterHolderWithInheritance(page, zone, parameterPath); 1062 return zoneViewParameterHolder.isPresent() ? zoneViewParameterHolder.get().getValue() : null; 1063 } 1064 1065 /** 1066 * Get the zone item parameter value 1067 * @param <T> type of the value to retrieve 1068 * @param zoneItem the zone item 1069 * @param parameterPath the parameter path 1070 * @return the zone item parameter value. Can be null. 1071 */ 1072 public <T extends Object> T getZoneItemParameterValue(ZoneItem zoneItem, String parameterPath) 1073 { 1074 ModelAwareDataHolder zoneItemParametersHolder = zoneItem.getZoneItemParametersHolder(); 1075 return zoneItemParametersHolder != null ? zoneItemParametersHolder.getValue(parameterPath) : null; 1076 } 1077 1078 /** 1079 * Get the content parameter value 1080 * @param <T> type of the value to retrieve 1081 * @param zoneItem the zone item 1082 * @param viewName the content view name 1083 * @param parameterPath the parameter path 1084 * @return the content parameter value. Can be null. 1085 */ 1086 public <T extends Object> T getContentParameterValue(ZoneItem zoneItem, String viewName, String parameterPath) 1087 { 1088 ModelAwareDataHolder contentParametersHolder = zoneItem.getContentViewParametersHolder(viewName); 1089 return contentParametersHolder != null ? contentParametersHolder.getValue(parameterPath) : null; 1090 } 1091 1092 /** 1093 * Get the service parameter value 1094 * @param <T> type of the value to retrieve 1095 * @param zoneItem the zone item 1096 * @param viewName the service view name 1097 * @param parameterPath the parameter path 1098 * @return the service parameter value. Can be null. 1099 */ 1100 public <T extends Object> T getServiceParameterValue(ZoneItem zoneItem, String viewName, String parameterPath) 1101 { 1102 ModelAwareDataHolder serviceParametersHolder = zoneItem.getServiceViewParametersHolder(viewName); 1103 return serviceParametersHolder != null ? serviceParametersHolder.getValue(parameterPath) : null; 1104 } 1105 1106 private void _addViewItems(View sourceView, View destView) 1107 { 1108 for (ViewItem viewItem : sourceView.getViewItems()) 1109 { 1110 if (!destView.hasModelViewItem(viewItem.getName())) 1111 { 1112 destView.addViewItem(viewItem); 1113 } 1114 } 1115 } 1116 1117 private void _addParameters(Collection<? extends ModelItem> modelItems, ViewParametersModel viewParametersModel) 1118 { 1119 for (ModelItem item : modelItems) 1120 { 1121 viewParametersModel.addModelItem(item); 1122 } 1123 } 1124 1125 private Optional<ViewParameterHolder> _getViewParamaterHolder(ModelAwareDataHolder dataHolder, String parameterPath) 1126 { 1127 if (dataHolder == null) 1128 { 1129 // No holder, return null 1130 return Optional.empty(); 1131 } 1132 1133 else if (!dataHolder.hasDefinition(parameterPath)) 1134 { 1135 getLogger().warn("The attribute '{}' is not defined by the model", parameterPath); 1136 return Optional.empty(); 1137 } 1138 1139 else if (!dataHolder.hasValue(parameterPath)) 1140 { 1141 // No value, return null 1142 return Optional.empty(); 1143 } 1144 1145 else 1146 { 1147 return Optional.of(new ViewParameterHolder(dataHolder, parameterPath)); 1148 } 1149 } 1150 1151 /** 1152 * Object representing the data holder of the parameter with the path of the parameter in this holder 1153 */ 1154 public static class ViewParameterHolder 1155 { 1156 private ModelAwareDataHolder _dataHolder; 1157 private String _parameterPath; 1158 1159 /** 1160 * Constructor for view parameter holder 1161 * @param dataHolder the holder containing the parameter 1162 * @param parameterPath the path of the parameter in the holder 1163 */ 1164 public ViewParameterHolder(ModelAwareDataHolder dataHolder, String parameterPath) 1165 { 1166 this._dataHolder = dataHolder; 1167 this._parameterPath = parameterPath; 1168 } 1169 1170 /** 1171 * Get the holder containing the parameter 1172 * @return the holder containing the parameter 1173 */ 1174 public ModelAwareDataHolder getDataHolder() 1175 { 1176 return this._dataHolder; 1177 } 1178 1179 /** 1180 * Get the path of the parameter in the holder 1181 * @return the path of the parameter in the holder 1182 */ 1183 public String getPath() 1184 { 1185 return this._parameterPath; 1186 } 1187 1188 /** 1189 * Get the parameter value 1190 * @param <T> type of the value to retrieve 1191 * @return the parameter value 1192 */ 1193 public <T extends Object> T getValue() 1194 { 1195 return this._dataHolder.getValue(this._parameterPath); 1196 } 1197 } 1198}