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