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.ade.sitemap; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.configuration.CmsConfigurationReader; 032import org.opencms.file.CmsObject; 033import org.opencms.main.OpenCms; 034import org.opencms.xml.CmsXmlUtils; 035import org.opencms.xml.content.CmsXmlContent; 036import org.opencms.xml.types.I_CmsXmlContentValue; 037 038import java.util.HashMap; 039import java.util.LinkedHashMap; 040import java.util.List; 041import java.util.Locale; 042import java.util.Map; 043 044/** 045 * Performs attribute changes in a sitemap configuration file CmsXmlContent instance. 046 */ 047public class CmsSitemapAttributeUpdater { 048 049 /** The CmsObject to use. */ 050 private CmsObject m_cms; 051 052 /** The XML content object containing the sitemap configuration. */ 053 private CmsXmlContent m_sitemapConfig; 054 055 /** 056 * Creates a new instance. 057 * 058 * @param cms the CmsObject to use 059 * @param sitemapConfig the sitemap configuration XML content 060 */ 061 public CmsSitemapAttributeUpdater(CmsObject cms, CmsXmlContent sitemapConfig) { 062 063 m_cms = cms; 064 m_sitemapConfig = sitemapConfig; 065 } 066 067 /** 068 * Given a map of attribute values (usually from the attribute editor), this method computes the necessary updates to perform. 069 * 070 * <p>Attribute values that match the inherited attribute from a parent sitemap configuration should cause the attribute to be removed. 071 * 072 * @param newAttributes the map of attributes 073 * @param config the sitemap config we are currently working on 074 * 075 * @return the map of updates (with null values indicating that the key should be removed) 076 */ 077 public static Map<String, String> computeUpdatesRelativeToInheritedValues( 078 Map<String, String> newAttributes, 079 CmsADEConfigData config) { 080 081 Map<String, String> updates = new HashMap<>(); 082 CmsADEConfigData parentConfig = config.parent(); 083 for (Map.Entry<String, String> entry : newAttributes.entrySet()) { 084 String attrName = entry.getKey(); 085 String attrValue = entry.getValue(); 086 String updateValue = attrValue; 087 if (parentConfig != null) { 088 String parentValue = parentConfig.getAttribute(attrName, null); 089 if ((parentValue != null) && parentValue.equals(attrValue)) { 090 updateValue = null; 091 } 092 } 093 if ("".equals(attrValue)) { 094 updateValue = null; 095 } 096 updates.put(attrName, updateValue); 097 } 098 return updates; 099 } 100 101 /** 102 * Gets the sitemap attributes that are currently stored in the XML content. 103 * 104 * @return the map of sitemap attributes 105 */ 106 public Map<String, String> getAttributesFromContent() { 107 108 Map<String, String> allValues = new LinkedHashMap<>(); 109 List<I_CmsXmlContentValue> attributeValues = m_sitemapConfig.getValues( 110 CmsConfigurationReader.N_ATTRIBUTE, 111 Locale.ENGLISH); 112 for (I_CmsXmlContentValue attr : attributeValues) { 113 I_CmsXmlContentValue keyValue = m_sitemapConfig.getValue( 114 CmsXmlUtils.concatXpath(attr.getPath(), CmsConfigurationReader.N_KEY), 115 Locale.ENGLISH); 116 I_CmsXmlContentValue valueValue = m_sitemapConfig.getValue( 117 CmsXmlUtils.concatXpath(attr.getPath(), CmsConfigurationReader.N_VALUE), 118 Locale.ENGLISH); 119 allValues.put(keyValue.getStringValue(m_cms), valueValue.getStringValue(m_cms)); 120 } 121 return allValues; 122 } 123 124 /** 125 * Gets the XML content which this object operates on. 126 * @return the XML content 127 */ 128 public CmsXmlContent getContent() { 129 130 return m_sitemapConfig; 131 } 132 133 /** 134 * Completely replaces the sitemap attributes in the XML content with the entries from the map passed as a parameter. 135 * 136 * @param allValues the new sitemap attributes that should replace the existing ones 137 */ 138 public void replaceAttributes(Map<String, String> allValues) { 139 140 while (m_sitemapConfig.hasValue(CmsConfigurationReader.N_ATTRIBUTE, Locale.ENGLISH)) { 141 m_sitemapConfig.removeValue(CmsConfigurationReader.N_ATTRIBUTE, Locale.ENGLISH, 0); 142 } 143 CmsObject cms = m_cms; 144 for (Map.Entry<String, String> entry : allValues.entrySet()) { 145 I_CmsXmlContentValue newAttrValue = m_sitemapConfig.addValue( 146 cms, 147 CmsConfigurationReader.N_ATTRIBUTE, 148 Locale.ENGLISH, 149 0); 150 I_CmsXmlContentValue newKeyValue = m_sitemapConfig.getValue( 151 CmsXmlUtils.concatXpath(newAttrValue.getPath(), CmsConfigurationReader.N_KEY), 152 Locale.ENGLISH); 153 I_CmsXmlContentValue newValueValue = m_sitemapConfig.getValue( 154 CmsXmlUtils.concatXpath(newAttrValue.getPath(), CmsConfigurationReader.N_VALUE), 155 Locale.ENGLISH); 156 newKeyValue.setStringValue(cms, entry.getKey()); 157 newValueValue.setStringValue(cms, entry.getValue()); 158 } 159 } 160 161 /** 162 * Saves the attributes coming from the editor dialog. 163 * 164 * <p>This method replaces values that match values inherited from a parent configuration with null (not set). 165 * 166 * @param attributes the attributes to save 167 * @return true if any changes were made 168 */ 169 public boolean saveAttributesFromEditorDialog(Map<String, String> attributes) { 170 171 CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache( 172 m_cms, 173 m_sitemapConfig.getFile().getRootPath()); 174 Map<String, String> updates = computeUpdatesRelativeToInheritedValues(attributes, config); 175 return updateAttributes(updates); 176 } 177 178 /** 179 * Performs a set of attribute changes. 180 * 181 * <p>The map given as an argument may contain null values. In that case, the corresponding attribute 182 * is removed from the XML content. 183 * 184 * @param attributeUpdates a map of attributes 185 * @return true if any attribute changes were necessary in the XML content 186 */ 187 public boolean updateAttributes(Map<String, String> attributeUpdates) { 188 189 Map<String, String> oldValues = getAttributesFromContent(); 190 Map<String, String> newValues = new LinkedHashMap<>(oldValues); 191 for (Map.Entry<String, String> entry : attributeUpdates.entrySet()) { 192 String key = entry.getKey(); 193 String value = entry.getValue(); 194 if (value != null) { 195 newValues.put(key, value); 196 } else { 197 newValues.remove(key); 198 } 199 } 200 boolean changed = !oldValues.equals(newValues); 201 if (changed) { 202 replaceAttributes(newValues); 203 } 204 return changed; 205 206 } 207 208}