001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.xml.containerpage; 029 030import org.opencms.main.OpenCms; 031import org.opencms.util.CmsMacroResolver; 032import org.opencms.util.CmsStringUtil; 033import org.opencms.util.CmsUUID; 034import org.opencms.xml.content.CmsXmlContentProperty; 035 036import java.util.ArrayList; 037import java.util.Collection; 038import java.util.Collections; 039import java.util.LinkedHashMap; 040import java.util.LinkedHashSet; 041import java.util.List; 042import java.util.Locale; 043import java.util.Map; 044import java.util.Set; 045 046import org.apache.commons.lang3.builder.ToStringBuilder; 047 048/** 049 * A bean containing formatter configuration data as strings.<p> 050 * 051 * @since 8.0.0 052 */ 053public class CmsFormatterBean implements I_CmsFormatterBean { 054 055 /** Default rank for formatters from formatter configuration files. */ 056 public static final int DEFAULT_CONFIGURATION_RANK = 1000; 057 058 /** Default rank for formatters defined in schema. */ 059 public static final int DEFAULT_SCHEMA_RANK = 10000; 060 061 /** Default formatter type constant. */ 062 public static final String PREVIEW_TYPE = "_PREVIEW_"; 063 064 /** The width of the preview window for the formatters. */ 065 public static final int PREVIEW_WIDTH = 640; 066 067 /** Wildcard formatter type for width based formatters. */ 068 public static final String WILDCARD_TYPE = "*"; 069 070 /** The formatter container type. */ 071 protected Set<String> m_containerTypes; 072 073 /** CSS Head includes. */ 074 protected Set<String> m_cssHeadIncludes = new LinkedHashSet<String>(); 075 076 /** The description text for the formatter. */ 077 protected String m_description; 078 079 /** Provides the display type. If empty if this formatter should not be used by the display tag. */ 080 protected String m_displayType; 081 082 /** The id for this formatter. */ 083 protected String m_id; 084 085 /** Inline CSS snippets. */ 086 protected String m_inlineCss; 087 088 /** Inline Javascript snippets. */ 089 protected String m_inlineJavascript; 090 091 /** Is the formatter automatically enabled? */ 092 protected boolean m_isAutoEnabled; 093 094 /** True if this formatter can be used for detail views. */ 095 protected boolean m_isDetail; 096 097 /** Is the formatter from a formatter configuration file? */ 098 protected boolean m_isFromFormatterConfigFile; 099 100 /** Indicates if this formatter is to be used as preview in the ADE gallery GUI. */ 101 protected boolean m_isPreviewFormatter; 102 103 /** JavaScript head includes. */ 104 protected List<String> m_javascriptHeadIncludes = new ArrayList<String>(); 105 106 /** The formatter JSP. */ 107 protected String m_jspRootPath; 108 109 /** The UUID of the JSP resource for this formatter. */ 110 protected CmsUUID m_jspStructureId; 111 112 /** The location this formatter was configured in. */ 113 protected String m_location; 114 115 /** If true, will match any container/width combination. */ 116 protected boolean m_matchAll; 117 118 /** The formatter max width. */ 119 protected int m_maxWidth; 120 121 /** The meta mappings. */ 122 protected List<CmsMetaMapping> m_metaMappings; 123 124 /** The formatter min width. */ 125 protected int m_minWidth; 126 127 /** Indicates whether nested formatter settings should be displayed. */ 128 protected boolean m_nestedFormatterSettings; 129 130 /** The nice name. */ 131 protected String m_niceName; 132 133 /** The rank. */ 134 protected int m_rank; 135 136 /** The resource type name. */ 137 protected Collection<String> m_resourceTypeNames; 138 139 /** Indicates if the content should be searchable in the online index when this formatter is used. */ 140 protected boolean m_search; 141 142 /** The settings. */ 143 protected Map<String, CmsXmlContentProperty> m_settings = new LinkedHashMap<String, CmsXmlContentProperty>(); 144 145 /** Indicating if this formatter will always render all nested containers. */ 146 protected boolean m_strictContainers; 147 148 /** Indicates whether meta mappings should be applied for all elements. */ 149 protected boolean m_useMetaMappingsForNormalElements; 150 151 /** Flag indicating this formatter allows settings to be edited in the content editor. */ 152 private boolean m_isAllowsSettingsInEditor; 153 154 /** Map of attributes. */ 155 private Map<String, String> m_attributes = Collections.emptyMap(); 156 157 /** 158 * Constructor for creating a new formatter configuration with resource structure id.<p> 159 * 160 * @param containerTypes the formatter container types 161 * @param jspRootPath the formatter JSP VFS root path 162 * @param jspStructureId the structure id of the formatter JSP 163 * @param minWidth the formatter min width 164 * @param maxWidth the formatter max width 165 * @param preview indicates if this formatter is to be used for the preview in the ADE gallery GUI 166 * @param searchContent indicates if the content should be searchable in the online index when this formatter is used 167 * @param location the location where this formatter was defined, should be an OpenCms VFS resource path 168 * @param cssHeadIncludes the CSS head includes 169 * @param inlineCss the in-line CSS 170 * @param javascriptHeadIncludes the JavaScript headincludes 171 * @param inlineJavascript the in-line JavaScript 172 * @param niceName the configuration display name 173 * @param description the description text for the formatter 174 * @param resourceTypeNames the resource type names 175 * @param rank the configuration rank 176 * @param id the configuration id 177 * @param settings the settings configuration 178 * @param isFromConfigFile <code>true</code> if configuration file based 179 * @param isAutoEnabled <code>true</code> if auto enabled 180 * @param isDetail <code>true</code> if detail formatter 181 * @param displayType the display type 182 * @param isAllowsSettingsInEditor whether this formatter allows settings to be edited in the content editor 183 * @param strictContainers <code>true</code> if this formatter will always render all nested containers 184 * @param nestedFormatterSettings indicates whether nested formatter settings should be displayed 185 * @param metaMappings the meta mappings 186 * @param attributes the formatter attributes 187 * @param useMetaMappingsForNormalElements if true, meta mappings will be evaluated for normal container elements, not just detail elements 188 */ 189 public CmsFormatterBean( 190 Set<String> containerTypes, 191 String jspRootPath, 192 CmsUUID jspStructureId, 193 int minWidth, 194 int maxWidth, 195 boolean preview, 196 boolean searchContent, 197 String location, 198 List<String> cssHeadIncludes, 199 String inlineCss, 200 List<String> javascriptHeadIncludes, 201 String inlineJavascript, 202 String niceName, 203 String description, 204 Collection<String> resourceTypeNames, 205 int rank, 206 String id, 207 Map<String, CmsXmlContentProperty> settings, 208 boolean isFromConfigFile, 209 boolean isAutoEnabled, 210 boolean isDetail, 211 String displayType, 212 boolean isAllowsSettingsInEditor, 213 boolean strictContainers, 214 boolean nestedFormatterSettings, 215 List<CmsMetaMapping> metaMappings, 216 Map<String, String> attributes, 217 boolean useMetaMappingsForNormalElements) { 218 219 m_jspRootPath = jspRootPath; 220 m_jspStructureId = jspStructureId; 221 m_containerTypes = containerTypes; 222 m_minWidth = minWidth; 223 m_maxWidth = maxWidth; 224 225 m_isPreviewFormatter = preview; 226 m_search = searchContent; 227 m_location = location; 228 m_description = description; 229 230 m_id = id; 231 m_niceName = niceName; 232 m_resourceTypeNames = resourceTypeNames; 233 m_rank = rank; 234 m_inlineCss = inlineCss; 235 m_inlineJavascript = inlineJavascript; 236 m_javascriptHeadIncludes.addAll(javascriptHeadIncludes); 237 m_cssHeadIncludes.addAll(cssHeadIncludes); 238 m_settings.putAll(settings); 239 m_isFromFormatterConfigFile = isFromConfigFile; 240 m_isAutoEnabled = isAutoEnabled; 241 m_isDetail = isDetail; 242 m_displayType = displayType; 243 m_nestedFormatterSettings = nestedFormatterSettings; 244 m_strictContainers = strictContainers; 245 m_metaMappings = metaMappings; 246 m_useMetaMappingsForNormalElements = useMetaMappingsForNormalElements; 247 m_isAllowsSettingsInEditor = isAllowsSettingsInEditor; 248 m_attributes = attributes != null ? attributes : Collections.emptyMap(); 249 } 250 251 /** 252 * Constructor for creating a new formatter configuration with resource structure id.<p> 253 * 254 * @param containerType the formatter container types 255 * @param rootPath the formatter JSP VFS root path 256 * @param structureId the structure id of the formatter JSP 257 * @param minWidth the formatter min width 258 * @param maxWidth the formatter max width 259 * @param preview indicates if this formatter is to be used for the preview in the ADE gallery GUI 260 * @param searchContent indicates if the content should be searchable in the online index when this formatter is used 261 * @param location the location where this formatter was defined, should be an OpenCms VFS resource path 262 */ 263 public CmsFormatterBean( 264 String containerType, 265 String rootPath, 266 CmsUUID structureId, 267 int minWidth, 268 int maxWidth, 269 boolean preview, 270 boolean searchContent, 271 String location) { 272 273 this( 274 isWildcardType(containerType) ? Collections.<String> emptySet() : Collections.singleton(containerType), 275 rootPath, 276 structureId, 277 minWidth, 278 maxWidth, 279 preview, 280 searchContent, 281 location, 282 Collections.<String> emptyList(), 283 "", 284 Collections.<String> emptyList(), 285 "", 286 null, 287 rootPath, 288 Collections.<String> emptySet(), 289 1000, 290 null, 291 Collections.<String, CmsXmlContentProperty> emptyMap(), 292 false, 293 false, 294 true, 295 null, 296 false, 297 false, 298 false, 299 null, 300 null, 301 false); 302 303 } 304 305 /** 306 * Constructor for creating a new formatter configuration without resource structure id.<p> 307 * 308 * @param containerType the formatter container type 309 * @param jspRootPath the formatter JSP VFS root path 310 * @param minWidthStr the formatter min width 311 * @param maxWidthStr the formatter max width 312 * @param preview indicates if this formatter is to be used for the preview in the ADE gallery GUI 313 * @param searchContent indicates if the content should be searchable in the online index when this formatter is used 314 * @param location the location where this formatter was defined, should be an OpenCms VFS resource path 315 */ 316 public CmsFormatterBean( 317 String containerType, 318 String jspRootPath, 319 String minWidthStr, 320 String maxWidthStr, 321 String preview, 322 String searchContent, 323 String location) { 324 325 m_jspRootPath = jspRootPath; 326 m_containerTypes = Collections.singleton(containerType); 327 if (isWildcardType(containerType)) { 328 m_containerTypes = Collections.emptySet(); 329 } 330 m_minWidth = -1; 331 m_maxWidth = Integer.MAX_VALUE; 332 333 if (m_containerTypes.isEmpty()) { 334 // wildcard formatter; index by width 335 // if no width available, use -1 336 337 try { 338 m_minWidth = Integer.parseInt(minWidthStr); 339 } catch (NumberFormatException e) { 340 //ignore; width will be -1 341 } 342 try { 343 m_maxWidth = Integer.parseInt(maxWidthStr); 344 } catch (NumberFormatException e) { 345 //ignore; maxWidth will be max. integer 346 } 347 } 348 349 m_isPreviewFormatter = Boolean.valueOf(preview).booleanValue(); 350 351 m_search = CmsStringUtil.isEmptyOrWhitespaceOnly(searchContent) 352 ? true 353 : Boolean.valueOf(searchContent).booleanValue(); 354 355 m_location = location; 356 m_rank = DEFAULT_SCHEMA_RANK; 357 } 358 359 /** 360 * Constructor for creating a formatter bean which matches all container/width combinations.<p> 361 * 362 * @param jspRootPath the jsp root path 363 * @param jspStructureId the jsp structure id 364 * @param location the formatter location 365 * @param preview the preview formatter flag 366 */ 367 CmsFormatterBean(String jspRootPath, CmsUUID jspStructureId, String location, boolean preview) { 368 369 this( 370 Collections.<String> emptySet(), 371 jspRootPath, 372 jspStructureId, 373 -1, 374 Integer.MAX_VALUE, 375 preview, 376 false, 377 location, 378 Collections.<String> emptyList(), 379 "", 380 Collections.<String> emptyList(), 381 "", 382 null, 383 jspRootPath, 384 Collections.<String> emptySet(), 385 DEFAULT_SCHEMA_RANK, 386 null, 387 Collections.<String, CmsXmlContentProperty> emptyMap(), 388 false, 389 false, 390 true, 391 null, 392 false, 393 false, 394 false, 395 null, 396 Collections.emptyMap(), 397 false); 398 m_matchAll = true; 399 } 400 401 /** 402 * Checks if the given container type matches the ADE gallery preview type.<p> 403 * 404 * @param containerType the container type to check 405 * 406 * @return <code>true</code> if the given container type matches the ADE gallery preview type 407 */ 408 public static boolean isPreviewType(String containerType) { 409 410 return PREVIEW_TYPE.equals(containerType); 411 } 412 413 /** 414 * Checks whether the container type is a wildcard.<p> 415 * 416 * @param containerType the container type 417 * 418 * @return true if the container type is a wildcard 419 */ 420 private static boolean isWildcardType(String containerType) { 421 422 return CmsStringUtil.isEmptyOrWhitespaceOnly(containerType) || WILDCARD_TYPE.equals(containerType); 423 } 424 425 /** 426 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getAttributes() 427 */ 428 public Map<String, String> getAttributes() { 429 430 return m_attributes; 431 } 432 433 /** 434 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getContainerTypes() 435 */ 436 @Override 437 public Set<String> getContainerTypes() { 438 439 return m_containerTypes == null 440 ? Collections.<String> emptySet() 441 : Collections.unmodifiableSet(m_containerTypes); 442 } 443 444 /** 445 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getCssHeadIncludes() 446 */ 447 @Override 448 public Set<String> getCssHeadIncludes() { 449 450 return Collections.unmodifiableSet(m_cssHeadIncludes); 451 } 452 453 /** 454 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getDescription(Locale) 455 */ 456 public String getDescription(Locale locale) { 457 458 if (locale == null) { 459 return m_description; 460 } 461 CmsMacroResolver resolver = new CmsMacroResolver(); 462 resolver.setMessages(OpenCms.getWorkplaceManager().getMessages(locale)); 463 return resolver.resolveMacros(m_description); 464 } 465 466 /** 467 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getDisplayType() 468 */ 469 public String getDisplayType() { 470 471 return m_displayType; 472 } 473 474 /** 475 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getId() 476 */ 477 @Override 478 public String getId() { 479 480 return m_id; 481 } 482 483 /** 484 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getInlineCss() 485 */ 486 @Override 487 public String getInlineCss() { 488 489 return m_inlineCss; 490 } 491 492 /** 493 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getInlineJavascript() 494 */ 495 @Override 496 public String getInlineJavascript() { 497 498 return m_inlineJavascript; 499 } 500 501 /** 502 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getJavascriptHeadIncludes() 503 */ 504 @Override 505 public List<String> getJavascriptHeadIncludes() { 506 507 return Collections.unmodifiableList(m_javascriptHeadIncludes); 508 } 509 510 /** 511 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getJspRootPath() 512 */ 513 @Override 514 public String getJspRootPath() { 515 516 return m_jspRootPath; 517 } 518 519 /** 520 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getJspStructureId() 521 */ 522 @Override 523 public CmsUUID getJspStructureId() { 524 525 return m_jspStructureId; 526 } 527 528 /** 529 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getLocation() 530 */ 531 @Override 532 public String getLocation() { 533 534 return m_location; 535 } 536 537 /** 538 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getMaxWidth() 539 */ 540 @Override 541 public int getMaxWidth() { 542 543 return m_maxWidth; 544 } 545 546 /** 547 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getMetaMappings() 548 */ 549 public List<CmsMetaMapping> getMetaMappings() { 550 551 return m_metaMappings; 552 } 553 554 /** 555 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getMinWidth() 556 */ 557 @Override 558 public int getMinWidth() { 559 560 return m_minWidth; 561 } 562 563 /** 564 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getNiceName(Locale) 565 */ 566 @Override 567 public String getNiceName(Locale locale) { 568 569 if (locale == null) { 570 return m_niceName; 571 } 572 CmsMacroResolver resolver = new CmsMacroResolver(); 573 resolver.setMessages(OpenCms.getWorkplaceManager().getMessages(locale)); 574 return resolver.resolveMacros(m_niceName); 575 } 576 577 /** 578 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getRank() 579 */ 580 @Override 581 public int getRank() { 582 583 return m_rank; 584 } 585 586 /** 587 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getResourceTypeNames() 588 */ 589 @Override 590 public Collection<String> getResourceTypeNames() { 591 592 return m_resourceTypeNames; 593 } 594 595 /** 596 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#getSettings() 597 */ 598 @Override 599 public Map<String, CmsXmlContentProperty> getSettings() { 600 601 return Collections.unmodifiableMap(m_settings); 602 } 603 604 /** 605 * @see java.lang.Object#hashCode() 606 */ 607 @Override 608 public int hashCode() { 609 610 return getContainerTypes().hashCode() ^ ((m_minWidth * 33) ^ m_maxWidth); 611 } 612 613 /** 614 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#hasNestedFormatterSettings() 615 */ 616 public boolean hasNestedFormatterSettings() { 617 618 return m_nestedFormatterSettings; 619 } 620 621 /** 622 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isAllowsSettingsInEditor() 623 */ 624 public boolean isAllowsSettingsInEditor() { 625 626 return m_isAllowsSettingsInEditor; 627 } 628 629 /** 630 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isAutoEnabled() 631 */ 632 @Override 633 public boolean isAutoEnabled() { 634 635 return m_isAutoEnabled; 636 } 637 638 /** 639 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isDetailFormatter() 640 */ 641 public boolean isDetailFormatter() { 642 643 return m_isDetail; 644 } 645 646 /** 647 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isDisplayFormatter() 648 */ 649 public boolean isDisplayFormatter() { 650 651 return m_displayType != null; 652 } 653 654 /** 655 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isFromFormatterConfigFile() 656 */ 657 @Override 658 public boolean isFromFormatterConfigFile() { 659 660 return m_isFromFormatterConfigFile; 661 } 662 663 /** 664 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isMatchAll() 665 */ 666 @Override 667 public boolean isMatchAll() { 668 669 return m_matchAll || ((m_containerTypes != null) && m_containerTypes.contains(WILDCARD_TYPE)); 670 } 671 672 /** 673 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isPreviewFormatter() 674 */ 675 @Override 676 public boolean isPreviewFormatter() { 677 678 return m_isPreviewFormatter; 679 } 680 681 /** 682 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isSearchContent() 683 */ 684 @Override 685 public boolean isSearchContent() { 686 687 return m_search; 688 } 689 690 /** 691 * Returns whether this formatter will always render all nested containers.<p> 692 * 693 * @return <code>true</code> if this formatter will always render all nested containers 694 */ 695 public boolean isStrictContainers() { 696 697 return m_strictContainers; 698 } 699 700 /** 701 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#isTypeFormatter() 702 */ 703 @Override 704 public boolean isTypeFormatter() { 705 706 return !getContainerTypes().isEmpty(); 707 } 708 709 /** 710 * Sets the structure id of the JSP for this formatter.<p> 711 * 712 * This is "package visible" as it should be only called from {@link CmsFormatterConfiguration#initialize(org.opencms.file.CmsObject)}.<p> 713 * 714 * @param jspStructureId the structure id of the JSP for this formatter 715 */ 716 public void setJspStructureId(CmsUUID jspStructureId) { 717 718 // package visibility is wanted 719 m_jspStructureId = jspStructureId; 720 } 721 722 /** 723 * @see java.lang.Object#toString() 724 */ 725 @Override 726 public String toString() { 727 728 return ToStringBuilder.reflectionToString(this); 729 } 730 731 /** 732 * @see org.opencms.xml.containerpage.I_CmsFormatterBean#useMetaMappingsForNormalElements() 733 */ 734 @Override 735 public boolean useMetaMappingsForNormalElements() { 736 737 return m_useMetaMappingsForNormalElements; 738 } 739}