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.ade.configuration.CmsADEManager; 031import org.opencms.ade.containerpage.shared.CmsContainerElement; 032import org.opencms.ade.containerpage.shared.CmsContainerElement.ModelGroupState; 033import org.opencms.ade.containerpage.shared.CmsFormatterConfig; 034import org.opencms.ade.containerpage.shared.CmsInheritanceInfo; 035import org.opencms.file.CmsFile; 036import org.opencms.file.CmsObject; 037import org.opencms.file.CmsResource; 038import org.opencms.file.CmsResourceFilter; 039import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 040import org.opencms.file.types.CmsResourceTypeXmlContent; 041import org.opencms.file.types.I_CmsResourceType; 042import org.opencms.main.CmsException; 043import org.opencms.main.OpenCms; 044import org.opencms.util.CmsNullIgnoringConcurrentMap; 045import org.opencms.util.CmsUUID; 046import org.opencms.xml.CmsXmlContentDefinition; 047import org.opencms.xml.content.CmsXmlContent; 048import org.opencms.xml.content.CmsXmlContentFactory; 049import org.opencms.xml.content.CmsXmlContentPropertyHelper; 050 051import java.util.Collections; 052import java.util.HashMap; 053import java.util.Locale; 054import java.util.Map; 055 056import javax.servlet.ServletRequest; 057 058/** 059 * One element of a container in a container page.<p> 060 * 061 * @since 8.0 062 */ 063public class CmsContainerElementBean implements Cloneable { 064 065 /** Flag indicating if a new element should be created replacing the given one on first edit of a container-page. */ 066 private final boolean m_createNew; 067 068 /** The client ADE editor hash. */ 069 private transient String m_editorHash; 070 071 /** The element's structure id. */ 072 private CmsUUID m_elementId; 073 074 /** The formatter's structure id. */ 075 private CmsUUID m_formatterId; 076 077 /** The configured properties. */ 078 private Map<String, String> m_individualSettings; 079 080 /** The inheritance info of this element. */ 081 private CmsInheritanceInfo m_inheritanceInfo; 082 083 /** Indicates whether the represented resource is in memory only and not in the VFS. */ 084 private boolean m_inMemoryOnly; 085 086 /** Indicating if the element resource is released and not expired. */ 087 private boolean m_releasedAndNotExpired; 088 089 /** The resource of this element. */ 090 private transient CmsResource m_resource; 091 092 /** The settings of this element containing also default values. */ 093 private transient Map<String, String> m_settings; 094 095 /** The element site path, only set while rendering. */ 096 private String m_sitePath; 097 098 /** Indicates the element bean has a temporary file content set. */ 099 private boolean m_temporaryContent; 100 101 /** 102 * Creates a new container page element bean.<p> 103 * 104 * @param file the element's file 105 * @param formatterId the formatter's structure id, could be <code>null</code> 106 * @param individualSettings the element settings as a map of name/value pairs 107 * @param inMemoryOnly the in memory flag 108 * @param editorHash the editor hash to use 109 * @param createNew <code>true</code> if a new element should be created replacing the given one on first edit of a container-page 110 **/ 111 public CmsContainerElementBean( 112 CmsFile file, 113 CmsUUID formatterId, 114 Map<String, String> individualSettings, 115 boolean inMemoryOnly, 116 String editorHash, 117 boolean createNew) { 118 119 this(file.getStructureId(), formatterId, individualSettings, createNew); 120 m_inMemoryOnly = inMemoryOnly; 121 m_editorHash = editorHash; 122 m_resource = file; 123 } 124 125 /** 126 * Creates a new container page element bean.<p> 127 * 128 * @param elementId the element's structure id 129 * @param formatterId the formatter's structure id, could be <code>null</code> 130 * @param individualSettings the element settings as a map of name/value pairs 131 * @param createNew <code>true</code> if a new element should be created replacing the given one on first edit of a container-page 132 **/ 133 public CmsContainerElementBean( 134 CmsUUID elementId, 135 CmsUUID formatterId, 136 Map<String, String> individualSettings, 137 boolean createNew) { 138 139 m_elementId = elementId; 140 m_formatterId = formatterId; 141 Map<String, String> newSettings = (individualSettings == null 142 ? new HashMap<String, String>() 143 : new HashMap<String, String>(individualSettings)); 144 if (!newSettings.containsKey(CmsContainerElement.ELEMENT_INSTANCE_ID)) { 145 newSettings.put(CmsContainerElement.ELEMENT_INSTANCE_ID, new CmsUUID().toString()); 146 } 147 newSettings.values().removeAll(Collections.singletonList(null)); 148 m_individualSettings = Collections.unmodifiableMap(newSettings); 149 m_editorHash = m_elementId.toString() + getSettingsHash(); 150 m_createNew = createNew; 151 } 152 153 /** 154 * Constructor to enable wrapped elements.<p> 155 */ 156 protected CmsContainerElementBean() { 157 158 m_elementId = null; 159 m_createNew = false; 160 } 161 162 /** 163 * Cloning constructor.<p> 164 * 165 * @param createNew create new flag 166 * @param elementId element id 167 * @param formatterId formatter id 168 * @param individualSettings individual settings 169 * @param inheritanceInfo inheritance info 170 * @param inMemoryOnly in memory only flag 171 * @param temporaryContent temporary content flag 172 * @param releasedAndNotExpired released and not expired flag 173 * @param resource the resource/file object 174 * @param settings the settings 175 * @param sitePath the site path 176 */ 177 private CmsContainerElementBean( 178 boolean createNew, 179 CmsUUID elementId, 180 CmsUUID formatterId, 181 Map<String, String> individualSettings, 182 CmsInheritanceInfo inheritanceInfo, 183 boolean inMemoryOnly, 184 boolean temporaryContent, 185 boolean releasedAndNotExpired, 186 CmsResource resource, 187 Map<String, String> settings, 188 String sitePath) { 189 190 m_createNew = createNew; 191 m_elementId = elementId; 192 m_formatterId = formatterId; 193 m_individualSettings = Collections.unmodifiableMap(individualSettings); 194 m_inheritanceInfo = inheritanceInfo; 195 m_inMemoryOnly = inMemoryOnly; 196 m_releasedAndNotExpired = releasedAndNotExpired; 197 m_resource = resource; 198 setSettings(settings); 199 m_sitePath = sitePath; 200 m_temporaryContent = temporaryContent; 201 } 202 203 /** 204 * Clones the given element bean with a different formatter.<p> 205 * 206 * @param source the element to clone 207 * @param formatterId the new formatter id 208 * 209 * @return the element bean 210 */ 211 public static CmsContainerElementBean cloneWithFormatter(CmsContainerElementBean source, CmsUUID formatterId) { 212 213 CmsContainerElementBean result = source.clone(); 214 result.m_formatterId = formatterId; 215 return result; 216 } 217 218 /** 219 * Clones the given element bean with a different set of settings.<p> 220 * 221 * @param source the element to clone 222 * @param settings the new settings 223 * 224 * @return the element bean 225 */ 226 public static CmsContainerElementBean cloneWithSettings( 227 CmsContainerElementBean source, 228 Map<String, String> settings) { 229 230 boolean createNew = source.m_createNew; 231 if (settings.containsKey(CmsContainerElement.CREATE_AS_NEW)) { 232 createNew = Boolean.valueOf(settings.get(CmsContainerElement.CREATE_AS_NEW)).booleanValue(); 233 settings = new HashMap<String, String>(settings); 234 settings.remove(CmsContainerElement.CREATE_AS_NEW); 235 } 236 CmsContainerElementBean result = new CmsContainerElementBean( 237 source.m_elementId, 238 source.m_formatterId, 239 settings, 240 createNew); 241 result.m_resource = source.m_resource; 242 result.m_sitePath = source.m_sitePath; 243 result.m_inMemoryOnly = source.m_inMemoryOnly; 244 result.m_inheritanceInfo = source.m_inheritanceInfo; 245 if (result.m_inMemoryOnly) { 246 String editorHash = source.m_editorHash; 247 if (editorHash.contains(CmsADEManager.CLIENT_ID_SEPERATOR)) { 248 editorHash = editorHash.substring(0, editorHash.indexOf(CmsADEManager.CLIENT_ID_SEPERATOR)); 249 } 250 editorHash += result.getSettingsHash(); 251 result.m_editorHash = editorHash; 252 } 253 return result; 254 } 255 256 /** 257 * Creates an element bean for the given resource type.<p> 258 * <b>The represented resource will be in memory only and not in the VFS!!!.</b><p> 259 * 260 * @param cms the CMS context 261 * @param resourceType the resource type 262 * @param targetFolder the parent folder of the resource 263 * @param individualSettings the element settings as a map of name/value pairs 264 * @param isCopyModels if this element when used in models should be copied instead of reused 265 * @param locale the locale to use 266 * 267 * @return the created element bean 268 * @throws CmsException if something goes wrong creating the element 269 * @throws IllegalArgumentException if the resource type not instance of {@link org.opencms.file.types.CmsResourceTypeXmlContent} 270 */ 271 public static CmsContainerElementBean createElementForResourceType( 272 CmsObject cms, 273 I_CmsResourceType resourceType, 274 String targetFolder, 275 Map<String, String> individualSettings, 276 boolean isCopyModels, 277 Locale locale) 278 throws CmsException { 279 280 if (!(resourceType instanceof CmsResourceTypeXmlContent)) { 281 throw new IllegalArgumentException(); 282 } 283 284 byte[] content = new byte[0]; 285 String schema = ((CmsResourceTypeXmlContent)resourceType).getSchema(); 286 if (schema != null) { 287 // must set URI of OpenCms user context to parent folder of created resource, 288 // in order to allow reading of properties for default values 289 CmsObject newCms = OpenCms.initCmsObject(cms); 290 newCms.getRequestContext().setUri(targetFolder); 291 // unmarshal the content definition for the new resource 292 CmsXmlContentDefinition contentDefinition = CmsXmlContentDefinition.unmarshal(cms, schema); 293 CmsXmlContent xmlContent = CmsXmlContentFactory.createDocument( 294 newCms, 295 locale, 296 OpenCms.getSystemInfo().getDefaultEncoding(), 297 contentDefinition); 298 // adding all other available locales 299 for (Locale otherLocale : OpenCms.getLocaleManager().getAvailableLocales()) { 300 if (!locale.equals(otherLocale)) { 301 xmlContent.addLocale(newCms, otherLocale); 302 } 303 } 304 content = xmlContent.marshal(); 305 } 306 @SuppressWarnings("deprecation") 307 CmsFile file = new CmsFile( 308 CmsUUID.getNullUUID(), 309 CmsUUID.getNullUUID(), 310 targetFolder + "~", 311 resourceType.getTypeId(), 312 0, 313 cms.getRequestContext().getCurrentProject().getUuid(), 314 CmsResource.STATE_NEW, 315 0, 316 cms.getRequestContext().getCurrentUser().getId(), 317 0, 318 cms.getRequestContext().getCurrentUser().getId(), 319 CmsResource.DATE_RELEASED_DEFAULT, 320 CmsResource.DATE_EXPIRED_DEFAULT, 321 1, 322 content.length, 323 0, 324 0, 325 content); 326 CmsContainerElementBean elementBean = new CmsContainerElementBean( 327 file, 328 null, 329 individualSettings, 330 true, 331 resourceType.getTypeName() + getSettingsHash(individualSettings, isCopyModels), 332 isCopyModels); 333 return elementBean; 334 } 335 336 /** 337 * Gets the hash code for the element settings.<p> 338 * 339 * @param individualSettings the individual settings 340 * @param createNew the create new flag 341 * 342 * @return the hash code for the element settings 343 */ 344 private static String getSettingsHash(Map<String, String> individualSettings, boolean createNew) { 345 346 if (!individualSettings.isEmpty() || createNew) { 347 int hash = (individualSettings.toString() + createNew).hashCode(); 348 return CmsADEManager.CLIENT_ID_SEPERATOR + hash; 349 } 350 return ""; 351 } 352 353 /** 354 * Adds a formatter setting.<p> 355 * 356 * @param containerName the container name 357 * @param formatterId the formatter id 358 */ 359 public void addFormatterSetting(String containerName, String formatterId) { 360 361 Map<String, String> newSettings = new HashMap<String, String>(m_individualSettings); 362 newSettings.put(CmsFormatterConfig.getSettingsKeyForContainer(containerName), formatterId); 363 m_individualSettings = Collections.unmodifiableMap(newSettings); 364 if (m_inMemoryOnly) { 365 String editorHash = m_editorHash; 366 if (editorHash.contains(CmsADEManager.CLIENT_ID_SEPERATOR)) { 367 editorHash = editorHash.substring(0, editorHash.indexOf(CmsADEManager.CLIENT_ID_SEPERATOR)); 368 } 369 editorHash += getSettingsHash(); 370 m_editorHash = editorHash; 371 } else { 372 m_editorHash = m_elementId.toString() + getSettingsHash(); 373 } 374 } 375 376 /** 377 * @see java.lang.Object#clone() 378 */ 379 @Override 380 public CmsContainerElementBean clone() { 381 382 return new CmsContainerElementBean( 383 m_createNew, 384 m_elementId, 385 m_formatterId, 386 m_individualSettings, 387 m_inheritanceInfo, 388 m_inMemoryOnly, 389 m_temporaryContent, 390 m_releasedAndNotExpired, 391 m_resource, 392 m_settings, 393 m_sitePath); 394 } 395 396 /** 397 * Returns the ADE client editor has value.<p> 398 * 399 * @return the ADE client editor has value 400 */ 401 public String editorHash() { 402 403 if (m_editorHash == null) { 404 m_editorHash = m_elementId.toString() + getSettingsHash(); 405 } 406 return m_editorHash; 407 } 408 409 /** 410 * @see java.lang.Object#equals(java.lang.Object) 411 */ 412 @Override 413 public boolean equals(Object obj) { 414 415 if (!(obj instanceof CmsContainerElementBean)) { 416 return false; 417 } 418 return editorHash().equals(((CmsContainerElementBean)obj).editorHash()); 419 } 420 421 /** 422 * Returns the structure id of the formatter of this element.<p> 423 * 424 * @return the structure id of the formatter of this element 425 */ 426 public CmsUUID getFormatterId() { 427 428 return m_formatterId; 429 } 430 431 /** 432 * Returns the structure id of the resource of this element.<p> 433 * 434 * @return the structure id of the resource of this element 435 */ 436 public CmsUUID getId() { 437 438 return m_elementId; 439 } 440 441 /** 442 * Returns the settings of this element.<p> 443 * 444 * @return the settings of this element 445 */ 446 public Map<String, String> getIndividualSettings() { 447 448 return m_individualSettings; 449 } 450 451 /** 452 * Returns the inheritance info.<p> 453 * 454 * @return the inheritance info or <code>null</code> if not available 455 */ 456 public CmsInheritanceInfo getInheritanceInfo() { 457 458 return m_inheritanceInfo; 459 } 460 461 /** 462 * Returns the element instance id.<p> 463 * 464 * @return the element instance id 465 */ 466 public String getInstanceId() { 467 468 return getIndividualSettings().get(CmsContainerElement.ELEMENT_INSTANCE_ID); 469 } 470 471 /** 472 * Returns the resource of this element.<p> 473 * 474 * It is required to call {@link #initResource(CmsObject)} before this method can be used.<p> 475 * 476 * @return the resource of this element 477 * 478 * @see #initResource(CmsObject) 479 */ 480 public CmsResource getResource() { 481 482 return m_resource; 483 } 484 485 /** 486 * Returns the element settings including default values for settings not set.<p> 487 * Will return <code>null</code> if the element bean has not been initialized with {@link #initResource(org.opencms.file.CmsObject)}.<p> 488 * 489 * @return the element settings 490 */ 491 public Map<String, String> getSettings() { 492 493 return m_settings; 494 } 495 496 /** 497 * Returns the site path of the resource of this element.<p> 498 * 499 * It is required to call {@link #initResource(CmsObject)} before this method can be used.<p> 500 * 501 * @return the site path of the resource of this element 502 * 503 * @see #initResource(CmsObject) 504 */ 505 public String getSitePath() { 506 507 return m_sitePath; 508 } 509 510 /** 511 * Returns the resource type name.<p> 512 * 513 * @return the type name 514 */ 515 public String getTypeName() { 516 517 if (getResource() != null) { 518 return OpenCms.getResourceManager().getResourceType(getResource()).getTypeName(); 519 } else { 520 return "unknown"; 521 } 522 } 523 524 /** 525 * @see java.lang.Object#hashCode() 526 */ 527 @Override 528 public int hashCode() { 529 530 return m_editorHash.hashCode(); 531 } 532 533 /** 534 * Initializes the resource and the site path of this element.<p> 535 * 536 * @param cms the CMS context 537 * 538 * @throws CmsException if something goes wrong reading the element resource 539 */ 540 public void initResource(CmsObject cms) throws CmsException { 541 542 if (m_resource == null) { 543 m_resource = cms.readResource(getId(), CmsResourceFilter.IGNORE_EXPIRATION); 544 m_releasedAndNotExpired = m_resource.isReleasedAndNotExpired(cms.getRequestContext().getRequestTime()); 545 } else if (!isInMemoryOnly()) { 546 CmsUUID id = m_resource.getStructureId(); 547 if (id == null) { 548 id = getId(); 549 } 550 // the resource object may have a wrong root path, e.g. if it was created before the resource was moved 551 if (cms.getRequestContext().getCurrentProject().isOnlineProject()) { 552 m_resource = cms.readResource(id, CmsResourceFilter.IGNORE_EXPIRATION); 553 m_releasedAndNotExpired = m_resource.isReleasedAndNotExpired(cms.getRequestContext().getRequestTime()); 554 } else { 555 if (!isTemporaryContent()) { 556 m_resource = cms.readResource(getId(), CmsResourceFilter.IGNORE_EXPIRATION); 557 } 558 m_releasedAndNotExpired = m_resource.isReleasedAndNotExpired(cms.getRequestContext().getRequestTime()); 559 } 560 } 561 if (m_settings == null) { 562 setSettings(new HashMap<String, String>(getIndividualSettings())); 563 } 564 // redo on every init call to ensure sitepath is calculated for current site 565 m_sitePath = cms.getSitePath(m_resource); 566 } 567 568 /** 569 * Initializes the element settings.<p> 570 * 571 * @param cms the CMS context 572 * @param formatterBean the formatter configuration bean 573 * @param locale the content locale 574 * @param request the current request, if available 575 * @param presets the presets for container element settings 576 */ 577 public void initSettings( 578 CmsObject cms, 579 I_CmsFormatterBean formatterBean, 580 Locale locale, 581 ServletRequest request, 582 Map<String, String> presets) { 583 584 Map<String, String> mergedSettings; 585 if (formatterBean == null) { 586 mergedSettings = CmsXmlContentPropertyHelper.mergeDefaults( 587 cms, 588 m_resource, 589 getIndividualSettings(), 590 locale, 591 request); 592 } else { 593 mergedSettings = CmsXmlContentPropertyHelper.mergeDefaults( 594 cms, 595 OpenCms.getADEManager().getFormatterSettings(cms, formatterBean, getResource(), locale, request), 596 getIndividualSettings()); 597 } 598 if ((presets != null) && (presets.size() > 0)) { 599 mergedSettings.putAll(presets); 600 } 601 if (m_settings == null) { 602 setSettings(mergedSettings); 603 } else { 604 m_settings.putAll(mergedSettings); 605 } 606 } 607 608 /** 609 * Returns if the given element should be used as a copy model.<p> 610 * 611 * @return <code>true</code> if the given element should be used as a copy model 612 */ 613 public boolean isCopyModel() { 614 615 return Boolean.valueOf(getIndividualSettings().get(CmsContainerElement.USE_AS_COPY_MODEL)).booleanValue(); 616 } 617 618 /** 619 * Returns if a new element should be created replacing the given one on first edit of a container-page.<p> 620 * 621 * @return <code>true</code> if a new element should be created replacing the given one on first edit of a container-page 622 */ 623 public boolean isCreateNew() { 624 625 return m_createNew; 626 } 627 628 /** 629 * Tests whether this element refers to a group container.<p> 630 * 631 * @param cms the CmsObject used for VFS operations 632 * 633 * @return <code>true</code> if the container element refers to a group container 634 * 635 * @throws CmsException if something goes wrong 636 */ 637 public boolean isGroupContainer(CmsObject cms) throws CmsException { 638 639 if (m_resource == null) { 640 initResource(cms); 641 } 642 return CmsResourceTypeXmlContainerPage.GROUP_CONTAINER_TYPE_NAME.equals( 643 OpenCms.getResourceManager().getResourceType(m_resource).getTypeName()); 644 } 645 646 /** 647 * Returns whether this element refers to an inherited container element.<p> 648 * 649 * @param cms the CmsObject used for VFS operations 650 * 651 * @return <code>true</code> if the container element refers to an inherited container 652 * 653 * @throws CmsException if something goes wrong 654 */ 655 @SuppressWarnings("deprecation") 656 public boolean isInheritedContainer(CmsObject cms) throws CmsException { 657 658 if (m_resource == null) { 659 initResource(cms); 660 } 661 return OpenCms.getResourceManager().getResourceType( 662 CmsResourceTypeXmlContainerPage.INHERIT_CONTAINER_TYPE_NAME).getTypeId() == m_resource.getTypeId(); 663 } 664 665 /** 666 * Returns if the represented resource is in memory only and not persisted in the VFS.<p> 667 * 668 * @return <code>true</code> if the represented resource is in memory only and not persisted in the VFS 669 */ 670 public boolean isInMemoryOnly() { 671 672 return m_inMemoryOnly; 673 } 674 675 /** 676 * Returns if the given element is a model group.<p> 677 * 678 * @return <code>true</code> if the given element is a model group 679 */ 680 public boolean isModelGroup() { 681 682 ModelGroupState state = ModelGroupState.evaluate( 683 getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_STATE)); 684 return state == ModelGroupState.isModelGroup; 685 } 686 687 /** 688 * Returns if all instances of this element should be replaced within a copy model.<p> 689 * 690 * @return <code>true</code> if all instances of this element should be replaced within a copy model 691 */ 692 public boolean isModelGroupAlwaysReplace() { 693 694 return Boolean.parseBoolean(getIndividualSettings().get(CmsContainerElement.IS_MODEL_GROUP_ALWAYS_REPLACE)); 695 } 696 697 /** 698 * Returns if the element resource is released and not expired.<p> 699 * 700 * @return <code>true</code> if the element resource is released and not expired 701 */ 702 public boolean isReleasedAndNotExpired() { 703 704 return isInMemoryOnly() || m_releasedAndNotExpired; 705 } 706 707 /** 708 * Returns if the element resource contains temporary file content.<p> 709 * 710 * @return <code>true</code> if the element resource contains temporary file content 711 */ 712 public boolean isTemporaryContent() { 713 714 return m_temporaryContent; 715 } 716 717 /** 718 * Removes the instance id.<p> 719 */ 720 public void removeInstanceId() { 721 722 Map<String, String> newSettings = new HashMap<String, String>(m_individualSettings); 723 newSettings.remove(CmsContainerElement.ELEMENT_INSTANCE_ID); 724 m_individualSettings = Collections.unmodifiableMap(newSettings); 725 m_editorHash = m_elementId.toString() + getSettingsHash(); 726 } 727 728 /** 729 * Sets the formatter id.<p> 730 * 731 * @param formatterId the formatter id 732 */ 733 public void setFormatterId(CmsUUID formatterId) { 734 735 m_formatterId = formatterId; 736 } 737 738 /** 739 * Sets a historical file.<p> 740 * 741 * @param file the historical file 742 */ 743 public void setHistoryFile(CmsFile file) { 744 745 m_resource = file; 746 m_inMemoryOnly = true; 747 } 748 749 /** 750 * Sets the inheritance info for this element.<p> 751 * 752 * @param inheritanceInfo the inheritance info 753 */ 754 public void setInheritanceInfo(CmsInheritanceInfo inheritanceInfo) { 755 756 m_inheritanceInfo = inheritanceInfo; 757 } 758 759 /** 760 * Sets the element resource as a temporary file.<p> 761 * 762 * @param elementFile the temporary file 763 */ 764 public void setTemporaryFile(CmsFile elementFile) { 765 766 m_resource = elementFile; 767 m_temporaryContent = true; 768 } 769 770 /** 771 * @see java.lang.Object#toString() 772 */ 773 @Override 774 public String toString() { 775 776 return editorHash(); 777 } 778 779 /** 780 * Updates the individual settings.<p> 781 * 782 * This causes all merged settings (from defaults etc.) to be lost. 783 * 784 * @param newSettings the new settings 785 */ 786 public void updateIndividualSettings(Map<String, String> newSettings) { 787 788 m_individualSettings = Collections.unmodifiableMap(newSettings); 789 setSettings(getIndividualSettings()); 790 } 791 792 /** 793 * Gets the hash code for the element settings.<p> 794 * 795 * @return the hash code for the element settings 796 */ 797 private String getSettingsHash() { 798 799 String instanceId = getInstanceId(); 800 if (instanceId == null) { 801 throw new RuntimeException("Missing instance id"); 802 } 803 return CmsADEManager.CLIENT_ID_SEPERATOR + getInstanceId(); 804 } 805 806 /** 807 * Sets the settings map.<p> 808 * 809 * @param settings the settings 810 */ 811 private void setSettings(Map<String, String> settings) { 812 813 if (settings == null) { 814 m_settings = null; 815 } else { 816 m_settings = new CmsNullIgnoringConcurrentMap<String, String>(settings); 817 } 818 } 819}