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