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