All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.file.CmsProperty Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

The newest version!
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software GmbH & Co. KG, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.file;

import org.opencms.i18n.CmsLocaleManager;
import org.opencms.main.CmsRuntimeException;
import org.opencms.util.CmsStringUtil;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.RandomAccess;

import org.apache.commons.collections.Transformer;

/**
 * Represents a property (meta-information) mapped to a VFS resource.

* * A property is an object that contains three string values: a name, a property value which is mapped * to the structure record of a resource, and a property value which is mapped to the resource * record of a resource. A property object is valid if it has both values or just one value set. * Each property needs at least a name and one value set.

* * A property value mapped to the structure record of a resource is significant for a single * resource (sibling). A property value mapped to the resource record of a resource is significant * for all siblings of a resource record. This is possible by getting the "compound value" * (see {@link #getValue()}) of a property in case a property object has both values set. The compound * value of a property object is the value mapped to the structure record, because it's structure * value is more significant than it's resource value. This allows to set a property only one time * on the resource record, and the property takes effect on all siblings of this resource record.

* * The ID of the structure or resource record where a property value is mapped to is represented by * the "PROPERTY_MAPPING_ID" table attribute in the database. The "PROPERTY_MAPPING_TYPE" table * attribute (see {@link #STRUCTURE_RECORD_MAPPING} and {@link #RESOURCE_RECORD_MAPPING}) * determines whether the value of the "PROPERTY_MAPPING_ID" attribute of the current row is * a structure or resource record ID.

* * Property objects are written to the database using {@link org.opencms.file.CmsObject#writePropertyObject(String, CmsProperty)} * or {@link org.opencms.file.CmsObject#writePropertyObjects(String, List)}, no matter * whether you want to save a new (non-existing) property, update an existing property, or delete an * existing property. To delete a property you would write a property object with either the * structure and/or resource record values set to {@link #DELETE_VALUE} to indicate that a * property value should be deleted in the database. Set property values to null if they should * remain unchanged in the database when a property object is written. As for example you want to * update just the structure value of a property, you would set the structure value to the new string, * and the resource value to null (which is already the case by default).

* * Use {@link #setAutoCreatePropertyDefinition(boolean)} to set a boolean flag whether a missing property * definition should be created implicitly for a resource type when a property is written to the database. * The default value for this flag is false. Thus, you receive a CmsException if you try * to write a property of a resource with a resource type which lacks a property definition for * this resource type. It is not a good style to set {@link #setAutoCreatePropertyDefinition(boolean)} * on true to make writing properties to the database work in any case, because then you will loose * control about which resource types support which property definitions.

* * @since 6.0.0 */ public class CmsProperty implements Serializable, Cloneable, Comparable { /** Transforms a given properties map, to a map where the returned values for a property are * dependent on the locale. */ public static class CmsPropertyLocaleTransformer implements Transformer { /** The original properties map. */ private Map m_properties; /** The locale, w.r.t. which the properties should be accessed. */ private Locale m_locale; /** * Default constructor. * @param properties the "raw" properties map as read for a resource. * @param locale the locale w.r.t. which the properties should be accessed. */ public CmsPropertyLocaleTransformer(Map properties, Locale locale) { m_properties = null == properties ? new HashMap() : properties; m_locale = null == locale ? new Locale("") : locale; } /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ public Object transform(Object propertyName) { return readProperty((String)propertyName); } /** * Looks up a property in {@link #m_properties}, but returns the localized variant. * * @param propertyName the property to look up * @return the value of the property */ protected String readProperty(String propertyName) { if (null == m_locale) { return m_properties.get(propertyName); } else { return m_properties.get(getLocalizedKey(m_properties, propertyName, m_locale)); } } } /** * Signals that the resource property values of a resource * should be deleted using deleteAllProperties.

*/ public static final int DELETE_OPTION_DELETE_RESOURCE_VALUES = 3; /** * Signals that both the structure and resource property values of a resource * should be deleted using deleteAllProperties.

*/ public static final int DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES = 1; /** * Signals that the structure property values of a resource * should be deleted using deleteAllProperties.

*/ public static final int DELETE_OPTION_DELETE_STRUCTURE_VALUES = 2; /** * An empty string to decide that a property value should be deleted when this * property object is written to the database.

*/ public static final String DELETE_VALUE = ""; /** * Value of the "mapping-type" database attribute to indicate that a property value is mapped * to a resource record.

*/ public static final int RESOURCE_RECORD_MAPPING = 2; /** * Value of the "mapping-type" database attribute to indicate that a property value is mapped * to a structure record.

*/ public static final int STRUCTURE_RECORD_MAPPING = 1; /** Key used for a individual (structure) property value. */ public static final String TYPE_INDIVIDUAL = "individual"; /** Key used for a shared (resource) property value. */ public static final String TYPE_SHARED = "shared"; /** The delimiter value for separating values in a list, per default this is the | char. */ public static final char VALUE_LIST_DELIMITER = '|'; /** The list delimiter replacement String used if the delimiter itself is contained in a String value. */ public static final String VALUE_LIST_DELIMITER_REPLACEMENT = "%(ld)"; /** The delimiter value for separating values in a map, per default this is the = char. */ public static final char VALUE_MAP_DELIMITER = '='; /** The map delimiter replacement String used if the delimiter itself is contained in a String value. */ public static final String VALUE_MAP_DELIMITER_REPLACEMENT = "%(md)"; /** The null property object to be used in caches if a property is not found. */ private static final CmsProperty NULL_PROPERTY = new CmsProperty(); /** Serial version UID required for safe serialization. */ private static final long serialVersionUID = 93613508924212782L; /** * Static initializer required for freezing the {@link #NULL_PROPERTY}.

*/ static { NULL_PROPERTY.m_frozen = true; NULL_PROPERTY.m_name = ""; } /** * Boolean flag to decide if the property definition for this property should be created * implicitly on any write operation if doesn't exist already.

*/ private boolean m_autoCreatePropertyDefinition; /** Indicates if the property is frozen (required for NULL_PROPERTY). */ private boolean m_frozen; /** The name of this property. */ private String m_name; /** The origin root path of the property. */ private String m_origin; /** The value of this property attached to the resource record. */ private String m_resourceValue; /** The (optional) value list of this property attached to the resource record. */ private List m_resourceValueList; /** The (optional) value map of this property attached to the resource record. */ private Map m_resourceValueMap; /** The value of this property attached to the structure record. */ private String m_structureValue; /** The (optional) value list of this property attached to the structure record. */ private List m_structureValueList; /** The (optional) value map of this property attached to the structure record. */ private Map m_structureValueMap; /** * Creates a new CmsProperty object.

* * The structure and resource property values are initialized to null. The structure and * resource IDs are initialized to {@link org.opencms.util.CmsUUID#getNullUUID()}.

*/ public CmsProperty() { // nothing to do, all values will be initialized with null or false by default } /** * Creates a new CmsProperty object using the provided values.

* * If the property definition does not exist for the resource type it * is automatically created when this property is written. * * @param name the name of the property definition * @param structureValue the value to write as structure property * @param resourceValue the value to write as resource property */ public CmsProperty(String name, String structureValue, String resourceValue) { this(name, structureValue, resourceValue, true); } /** * Creates a new CmsProperty object using the provided values.

* * If null is supplied for the resource or structure value, this * value will not be available for this property.

* * @param name the name of the property definition * @param structureValue the value to write as structure property, or null * @param resourceValue the value to write as resource property , or null * @param autoCreatePropertyDefinition if true, the property definition for this property will be * created implicitly on any write operation if it doesn't exist already */ public CmsProperty(String name, String structureValue, String resourceValue, boolean autoCreatePropertyDefinition) { m_name = name.trim(); m_structureValue = structureValue; m_resourceValue = resourceValue; m_autoCreatePropertyDefinition = autoCreatePropertyDefinition; } /** * Searches in a list for the first occurrence of a {@link CmsProperty} object with the given name.

* * To check if the "null property" has been returned if a property was * not found, use {@link #isNullProperty()} on the result.

* * @param name a property name * @param list a list of {@link CmsProperty} objects * @return the index of the first occurrence of the name in they specified list, * or {@link CmsProperty#getNullProperty()} if the name is not found */ public static final CmsProperty get(String name, List list) { CmsProperty property = null; name = name.trim(); // choose the fastest method to traverse the list if (list instanceof RandomAccess) { for (int i = 0, n = list.size(); i < n; i++) { property = list.get(i); if (property.m_name.equals(name)) { return property; } } } else { Iterator i = list.iterator(); while (i.hasNext()) { property = i.next(); if (property.m_name.equals(name)) { return property; } } } return NULL_PROPERTY; } /** * Returns the value for the best matching local-specific property version. * * @param propertiesMap the "raw" property map * @param key the name of the property to search for * @param locale the locale to search for * * @return the key for the best matching local-specific property version. */ public static String getLocaleSpecificPropertyValue( Map propertiesMap, String key, Locale locale) { String localeSpecificKey = CmsProperty.getLocalizedKey(propertiesMap, key, locale); if (propertiesMap.containsKey(localeSpecificKey)) { return propertiesMap.get(localeSpecificKey).getValue(); } return null; } /** * Returns the key for the best matching local-specific property version. * * @param propertiesMap the "raw" property map * @param key the name of the property to search for * @param locale the locale to search for * * @return the key for the best matching local-specific property version. */ public static String getLocalizedKey(Map propertiesMap, String key, Locale locale) { List localizedKeys = CmsLocaleManager.getLocaleVariants(key, locale, true, false); for (String localizedKey : localizedKeys) { if (propertiesMap.containsKey(localizedKey)) { return localizedKey; } } return key; } /** * Returns the null property object.

* * @return the null property object */ public static final CmsProperty getNullProperty() { return NULL_PROPERTY; } /** * Transforms a list of CmsProperty objects with structure and resource values into a map with * CmsProperty object values keyed by property keys.

* * @param list a list of CmsProperty objects * @return a map with CmsPropery object values keyed by property keys */ public static Map getPropertyMap(List list) { Map result = null; String key = null; CmsProperty property = null; if ((list == null) || (list.size() == 0)) { return Collections.emptyMap(); } result = new HashMap(); // choose the fastest method to iterate the list if (list instanceof RandomAccess) { for (int i = 0, n = list.size(); i < n; i++) { property = list.get(i); key = property.getName(); result.put(key, property); } } else { Iterator i = list.iterator(); while (i.hasNext()) { property = i.next(); key = property.getName(); result.put(key, property); } } return result; } /** * Calls {@link #setAutoCreatePropertyDefinition(boolean)} for each * property object in the given List with the given value parameter.

* * This method will modify the objects in the input list directly.

* * @param list a list of {@link CmsProperty} objects to modify * @param value boolean value * * @return the modified list of {@link CmsProperty} objects * * @see #setAutoCreatePropertyDefinition(boolean) */ public static final List setAutoCreatePropertyDefinitions(List list, boolean value) { CmsProperty property; // choose the fastest method to traverse the list if (list instanceof RandomAccess) { for (int i = 0, n = list.size(); i < n; i++) { property = list.get(i); property.m_autoCreatePropertyDefinition = value; } } else { Iterator i = list.iterator(); while (i.hasNext()) { property = i.next(); property.m_autoCreatePropertyDefinition = value; } } return list; } /** * Calls {@link #setFrozen(boolean)} for each * {@link CmsProperty} object in the given List if it is not already frozen.

* * This method will modify the objects in the input list directly.

* * @param list a list of {@link CmsProperty} objects * * @return the modified list of properties * * @see #setFrozen(boolean) */ public static final List setFrozen(List list) { CmsProperty property; // choose the fastest method to traverse the list if (list instanceof RandomAccess) { for (int i = 0, n = list.size(); i < n; i++) { property = list.get(i); if (!property.isFrozen()) { property.setFrozen(true); } } } else { Iterator i = list.iterator(); while (i.hasNext()) { property = i.next(); if (!property.isFrozen()) { property.setFrozen(true); } } } return list; } /** * Transforms a Map of String values into a list of * {@link CmsProperty} objects with the property name set from the * Map key, and the structure value set from the Map value.

* * @param map a Map with String keys and String values * * @return a list of {@link CmsProperty} objects */ public static List toList(Map map) { if ((map == null) || (map.size() == 0)) { return Collections.emptyList(); } List result = new ArrayList(map.size()); Iterator> i = map.entrySet().iterator(); while (i.hasNext()) { Map.Entry e = i.next(); CmsProperty property = new CmsProperty(e.getKey(), e.getValue(), null); result.add(property); } return result; } /** * Transforms a list of {@link CmsProperty} objects into a Map which uses the property name as * Map key (String), and the property value as Map value (String).

* * @param list a list of {@link CmsProperty} objects * * @return a Map which uses the property names as * Map keys (String), and the property values as Map values (String) */ public static Map toMap(List list) { if ((list == null) || (list.size() == 0)) { return Collections.emptyMap(); } String name = null; String value = null; CmsProperty property = null; Map result = new HashMap(list.size()); // choose the fastest method to traverse the list if (list instanceof RandomAccess) { for (int i = 0, n = list.size(); i < n; i++) { property = list.get(i); name = property.m_name; value = property.getValue(); result.put(name, value); } } else { Iterator i = list.iterator(); while (i.hasNext()) { property = i.next(); name = property.m_name; value = property.getValue(); result.put(name, value); } } return result; } /** * Stores a collection of properties in a map, with the property names as keys.

* * @param properties the properties to store in the map * * @return the map with the property names as keys and the property objects as values */ public static Map toObjectMap(Iterable properties) { Map result = new LinkedHashMap(); for (CmsProperty property : properties) { result.put(property.getName(), property); } return result; } /** * Wraps a null value into a null property, and returns all other values unchanged.

* * @param prop the value to wrap * * @return a wrapped null property, or the original prop if it wasn't null */ public static CmsProperty wrapIfNull(CmsProperty prop) { if (prop == null) { return getNullProperty(); } else { return prop; } } /** * Checks if the property definition for this property will be * created implicitly on any write operation if doesn't already exist.

* * @return true, if the property definition for this property will be created implicitly on any write operation */ public boolean autoCreatePropertyDefinition() { return m_autoCreatePropertyDefinition; } /** * Creates a clone of this property.

* * @return a clone of this property * * @see #cloneAsProperty() */ @Override public CmsProperty clone() { return cloneAsProperty(); } /** * Creates a clone of this property that already is of type {@link CmsProperty}.

* * The cloned property will not be frozen.

* * @return a clone of this property that already is of type {@link CmsProperty} */ public CmsProperty cloneAsProperty() { if (this == NULL_PROPERTY) { // null property must never be cloned return NULL_PROPERTY; } CmsProperty clone = new CmsProperty(); clone.m_name = m_name; clone.m_structureValue = m_structureValue; clone.m_structureValueList = m_structureValueList; clone.m_resourceValue = m_resourceValue; clone.m_resourceValueList = m_resourceValueList; clone.m_autoCreatePropertyDefinition = m_autoCreatePropertyDefinition; clone.m_origin = m_origin; // the value for m_frozen does not need to be set as it is false by default return clone; } /** * Compares this property to another Object.

* * @param obj the other object to be compared * @return if the argument is a property object, returns zero if the name of the argument is equal to the name of this property object, * a value less than zero if the name of this property is lexicographically less than the name of the argument, * or a value greater than zero if the name of this property is lexicographically greater than the name of the argument */ public int compareTo(CmsProperty obj) { if (obj == this) { return 0; } return m_name.compareTo(obj.m_name); } /** * Tests if a specified object is equal to this CmsProperty object.

* * Two property objects are equal if their names are equal.

* * In case you want to compare the values as well as the name, * use {@link #isIdentical(CmsProperty)} instead.

* * @param obj another object * @return true, if the specified object is equal to this CmsProperty object * * @see #isIdentical(CmsProperty) */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof CmsProperty) { return ((CmsProperty)obj).m_name.equals(m_name); } return false; } /** * Returns the name of this property.

* * @return the name of this property */ public String getName() { return m_name; } /** * Returns the root path of the resource from which the property was read.

* * @return the root path of the resource from which the property was read */ public String getOrigin() { return m_origin; } /** * Returns the value of this property attached to the resource record.

* * @return the value of this property attached to the resource record */ public String getResourceValue() { return m_resourceValue; } /** * Returns the value of this property attached to the resource record, split as a list.

* * This list is build form the resource value, which is split into separate values * using the | char as delimiter. If the delimiter is not found, * then the list will contain one entry which is equal to {@link #getResourceValue()}.

* * @return the value of this property attached to the resource record, split as a (unmodifiable) list of Strings */ public List getResourceValueList() { if ((m_resourceValueList == null) && (m_resourceValue != null)) { // use lazy initializing of the list m_resourceValueList = createListFromValue(m_resourceValue); m_resourceValueList = Collections.unmodifiableList(m_resourceValueList); } return m_resourceValueList; } /** * Returns the value of this property attached to the resource record as a map.

* * This map is build from the used value, which is split into separate key/value pairs * using the | char as delimiter. If the delimiter is not found, * then the map will contain one entry.

* * The key/value pairs are separated with the =.

* * @return the value of this property attached to the resource record, as an (unmodifiable) map of Strings */ public Map getResourceValueMap() { if ((m_resourceValueMap == null) && (m_resourceValue != null)) { // use lazy initializing of the map m_resourceValueMap = createMapFromValue(m_resourceValue); m_resourceValueMap = Collections.unmodifiableMap(m_resourceValueMap); } return m_resourceValueMap; } /** * Returns the value of this property attached to the structure record.

* * @return the value of this property attached to the structure record */ public String getStructureValue() { return m_structureValue; } /** * Returns the value of this property attached to the structure record, split as a list.

* * This list is build form the structure value, which is split into separate values * using the | char as delimiter. If the delimiter is not found, * then the list will contain one entry which is equal to {@link #getStructureValue()}.

* * @return the value of this property attached to the structure record, split as a (unmodifiable) list of Strings */ public List getStructureValueList() { if ((m_structureValueList == null) && (m_structureValue != null)) { // use lazy initializing of the list m_structureValueList = createListFromValue(m_structureValue); m_structureValueList = Collections.unmodifiableList(m_structureValueList); } return m_structureValueList; } /** * Returns the value of this property attached to the structure record as a map.

* * This map is build from the used value, which is split into separate key/value pairs * using the | char as delimiter. If the delimiter is not found, * then the map will contain one entry.

* * The key/value pairs are separated with the =.

* * @return the value of this property attached to the structure record, as an (unmodifiable) map of Strings */ public Map getStructureValueMap() { if ((m_structureValueMap == null) && (m_structureValue != null)) { // use lazy initializing of the map m_structureValueMap = createMapFromValue(m_structureValue); m_structureValueMap = Collections.unmodifiableMap(m_structureValueMap); } return m_structureValueMap; } /** * Returns the compound value of this property.

* * The value returned is the value of {@link #getStructureValue()}, if it is not null. * Otherwise the value if {@link #getResourceValue()} is returned (which may also be null).

* * @return the compound value of this property */ public String getValue() { return (m_structureValue != null) ? m_structureValue : m_resourceValue; } /** * Returns the compound value of this property, or a specified default value, * if both the structure and resource values are null.

* * In other words, this method returns the defaultValue if this property object * is the null property (see {@link CmsProperty#getNullProperty()}).

* * @param defaultValue a default value which is returned if both the structure and resource values are null * * @return the compound value of this property, or the default value */ public String getValue(String defaultValue) { if (this == CmsProperty.NULL_PROPERTY) { // return the default value if this property is the null property return defaultValue; } // somebody might have set both values to null manually // on a property object different from the null property... return (m_structureValue != null) ? m_structureValue : ((m_resourceValue != null) ? m_resourceValue : defaultValue); } /** * Returns the compound value of this property, split as a list.

* * This list is build form the used value, which is split into separate values * using the | char as delimiter. If the delimiter is not found, * then the list will contain one entry.

* * The value returned is the value of {@link #getStructureValueList()}, if it is not null. * Otherwise the value of {@link #getResourceValueList()} is returned (which may also be null).

* * @return the compound value of this property, split as a (unmodifiable) list of Strings */ public List getValueList() { return (m_structureValue != null) ? getStructureValueList() : getResourceValueList(); } /** * Returns the compound value of this property, split as a list, or a specified default value list, * if both the structure and resource values are null.

* * In other words, this method returns the defaultValue if this property object * is the null property (see {@link CmsProperty#getNullProperty()}).

* * @param defaultValue a default value list which is returned if both the structure and resource values are null * * @return the compound value of this property, split as a (unmodifiable) list of Strings */ public List getValueList(List defaultValue) { if (this == CmsProperty.NULL_PROPERTY) { // return the default value if this property is the null property return defaultValue; } // somebody might have set both values to null manually // on a property object different from the null property... return (m_structureValue != null) ? getStructureValueList() : ((m_resourceValue != null) ? getResourceValueList() : defaultValue); } /** * Returns the compound value of this property as a map.

* * This map is build from the used value, which is split into separate key/value pairs * using the | char as delimiter. If the delimiter is not found, * then the map will contain one entry.

* * The key/value pairs are separated with the =.

* * The value returned is the value of {@link #getStructureValueMap()}, if it is not null. * Otherwise the value of {@link #getResourceValueMap()} is returned (which may also be null).

* * @return the compound value of this property as a (unmodifiable) map of Strings */ public Map getValueMap() { return (m_structureValue != null) ? getStructureValueMap() : getResourceValueMap(); } /** * Returns the compound value of this property as a map, or a specified default value map, * if both the structure and resource values are null.

* * In other words, this method returns the defaultValue if this property object * is the null property (see {@link CmsProperty#getNullProperty()}).

* * @param defaultValue a default value map which is returned if both the structure and resource values are null * * @return the compound value of this property as a (unmodifiable) map of Strings */ public Map getValueMap(Map defaultValue) { if (this == CmsProperty.NULL_PROPERTY) { // return the default value if this property is the null property return defaultValue; } // somebody might have set both values to null manually // on a property object different from the null property... return (m_structureValue != null) ? getStructureValueMap() : ((m_resourceValue != null) ? getResourceValueMap() : defaultValue); } /** * Returns the hash code of the property, which is based only on the property name, not on the values.

* * The resource and structure values are not taken into consideration for the hashcode generation * because the {@link #equals(Object)} implementation also does not take these into consideration.

* * @return the hash code of the property * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return m_name.hashCode(); } /** * Checks if the resource value of this property should be deleted when this * property object is written to the database.

* * @return true, if the resource value of this property should be deleted * @see CmsProperty#DELETE_VALUE */ public boolean isDeleteResourceValue() { return (m_resourceValue == DELETE_VALUE) || ((m_resourceValue != null) && (m_resourceValue.length() == 0)); } /** * Checks if the structure value of this property should be deleted when this * property object is written to the database.

* * @return true, if the structure value of this property should be deleted * @see CmsProperty#DELETE_VALUE */ public boolean isDeleteStructureValue() { return (m_structureValue == DELETE_VALUE) || ((m_structureValue != null) && (m_structureValue.length() == 0)); } /** * Returns true if this property is frozen, that is read only.

* * @return true if this property is frozen, that is read only */ public boolean isFrozen() { return m_frozen; } /** * Tests if a given CmsProperty is identical to this CmsProperty object.

* * The property object are identical if their name, structure and * resource values are all equals.

* * @param property another property object * @return true, if the specified object is equal to this CmsProperty object */ public boolean isIdentical(CmsProperty property) { boolean isEqual; // compare the name if (m_name == null) { isEqual = (property.getName() == null); } else { isEqual = m_name.equals(property.getName()); } // compare the structure value if (m_structureValue == null) { isEqual &= (property.getStructureValue() == null); } else { isEqual &= m_structureValue.equals(property.getStructureValue()); } // compare the resource value if (m_resourceValue == null) { isEqual &= (property.getResourceValue() == null); } else { isEqual &= m_resourceValue.equals(property.getResourceValue()); } return isEqual; } /** * Checks if this property object is the null property object.

* * @return true if this property object is the null property object */ public boolean isNullProperty() { return NULL_PROPERTY.equals(this); } /** * Sets the boolean flag to decide if the property definition for this property should be * created implicitly on any write operation if doesn't exist already.

* * @param value true, if the property definition for this property should be created implicitly on any write operation */ public void setAutoCreatePropertyDefinition(boolean value) { checkFrozen(); m_autoCreatePropertyDefinition = value; } /** * Sets the frozen state of the property, if set to true then this property is read only.

* * If the property is already frozen, then setting the frozen state to true again is allowed, * but setting the value to false causes a {@link CmsRuntimeException}.

* * @param frozen the frozen state to set */ public void setFrozen(boolean frozen) { if (!frozen) { checkFrozen(); } m_frozen = frozen; } /** * Sets the name of this property.

* * @param name the name to set */ public void setName(String name) { checkFrozen(); m_name = name.trim(); } /** * Sets the path of the resource from which the property was read.

* * @param originRootPath the root path of the root path from which the property was read */ public void setOrigin(String originRootPath) { checkFrozen(); m_origin = originRootPath; } /** * Sets the value of this property attached to the resource record.

* * @param resourceValue the value of this property attached to the resource record */ public void setResourceValue(String resourceValue) { checkFrozen(); m_resourceValue = resourceValue; m_resourceValueList = null; } /** * Sets the value of this property attached to the resource record from the given list of Strings.

* * The value will be created from the individual values of the given list, which are appended * using the | char as delimiter.

* * @param valueList the list of value (Strings) to attach to the resource record */ public void setResourceValueList(List valueList) { checkFrozen(); if (valueList != null) { m_resourceValueList = new ArrayList(valueList); m_resourceValueList = Collections.unmodifiableList(m_resourceValueList); m_resourceValue = createValueFromList(m_resourceValueList); } else { m_resourceValueList = null; m_resourceValue = null; } } /** * Sets the value of this property attached to the resource record from the given map of Strings.

* * The value will be created from the individual values of the given map, which are appended * using the | char as delimiter, the map keys and values are separated by a =.

* * @param valueMap the map of key/value (Strings) to attach to the resource record */ public void setResourceValueMap(Map valueMap) { checkFrozen(); if (valueMap != null) { m_resourceValueMap = new HashMap(valueMap); m_resourceValueMap = Collections.unmodifiableMap(m_resourceValueMap); m_resourceValue = createValueFromMap(m_resourceValueMap); } else { m_resourceValueMap = null; m_resourceValue = null; } } /** * Sets the value of this property attached to the structure record.

* * @param structureValue the value of this property attached to the structure record */ public void setStructureValue(String structureValue) { checkFrozen(); m_structureValue = structureValue; m_structureValueList = null; } /** * Sets the value of this property attached to the structure record from the given list of Strings.

* * The value will be created from the individual values of the given list, which are appended * using the | char as delimiter.

* * @param valueList the list of value (Strings) to attach to the structure record */ public void setStructureValueList(List valueList) { checkFrozen(); if (valueList != null) { m_structureValueList = new ArrayList(valueList); m_structureValueList = Collections.unmodifiableList(m_structureValueList); m_structureValue = createValueFromList(m_structureValueList); } else { m_structureValueList = null; m_structureValue = null; } } /** * Sets the value of this property attached to the structure record from the given map of Strings.

* * The value will be created from the individual values of the given map, which are appended * using the | char as delimiter, the map keys and values are separated by a =.

* * @param valueMap the map of key/value (Strings) to attach to the structure record */ public void setStructureValueMap(Map valueMap) { checkFrozen(); if (valueMap != null) { m_structureValueMap = new HashMap(valueMap); m_structureValueMap = Collections.unmodifiableMap(m_structureValueMap); m_structureValue = createValueFromMap(m_structureValueMap); } else { m_structureValueMap = null; m_structureValue = null; } } /** * Sets the value of this property as either shared or * individual value.

* * If the given type equals {@link CmsProperty#TYPE_SHARED} then * the value is set as a shared (resource) value, otherwise it * is set as individual (structure) value.

* * @param value the value to set * @param type the value type to set */ public void setValue(String value, String type) { checkFrozen(); setAutoCreatePropertyDefinition(true); if (TYPE_SHARED.equalsIgnoreCase(type)) { // set the provided value as shared (resource) value setResourceValue(value); } else { // set the provided value as individual (structure) value setStructureValue(value); } } /** * Returns a string representation of this property object.

* * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer strBuf = new StringBuffer(); strBuf.append("[").append(getClass().getName()).append(": "); strBuf.append("name: '").append(m_name).append("'"); strBuf.append(", value: '").append(getValue()).append("'"); strBuf.append(", structure value: '").append(m_structureValue).append("'"); strBuf.append(", resource value: '").append(m_resourceValue).append("'"); strBuf.append(", frozen: ").append(m_frozen); strBuf.append(", origin: ").append(m_origin); strBuf.append("]"); return strBuf.toString(); } /** * Checks if this property is frozen, that is read only.

*/ private void checkFrozen() { if (m_frozen) { throw new CmsRuntimeException(Messages.get().container(Messages.ERR_PROPERTY_FROZEN_1, toString())); } } /** * Returns the list value representation for the given String.

* * The given value is split along the | char.

* * @param value the value to create the list representation for * * @return the list value representation for the given String */ private List createListFromValue(String value) { if (value == null) { return null; } List result = CmsStringUtil.splitAsList(value, VALUE_LIST_DELIMITER); if (value.indexOf(VALUE_LIST_DELIMITER_REPLACEMENT) != -1) { List tempList = new ArrayList(result.size()); Iterator i = result.iterator(); while (i.hasNext()) { String item = i.next(); tempList.add(rebuildDelimiter(item, VALUE_LIST_DELIMITER, VALUE_LIST_DELIMITER_REPLACEMENT)); } result = tempList; } return result; } /** * Returns the map value representation for the given String.

* * The given value is split along the | char, the map keys and values are separated by a =.

* * @param value the value to create the map representation for * * @return the map value representation for the given String */ private Map createMapFromValue(String value) { if (value == null) { return null; } List entries = createListFromValue(value); Iterator i = entries.iterator(); Map result = new HashMap(entries.size()); boolean rebuildDelimiters = false; if (value.indexOf(VALUE_MAP_DELIMITER_REPLACEMENT) != -1) { rebuildDelimiters = true; } while (i.hasNext()) { String entry = i.next(); int index = entry.indexOf(VALUE_MAP_DELIMITER); if (index != -1) { String key = entry.substring(0, index); String val = ""; if ((index + 1) < entry.length()) { val = entry.substring(index + 1); } if (CmsStringUtil.isNotEmpty(key)) { if (rebuildDelimiters) { key = rebuildDelimiter(key, VALUE_MAP_DELIMITER, VALUE_MAP_DELIMITER_REPLACEMENT); val = rebuildDelimiter(val, VALUE_MAP_DELIMITER, VALUE_MAP_DELIMITER_REPLACEMENT); } result.put(key, val); } } } return result; } /** * Returns the single String value representation for the given value list.

* * @param valueList the value list to create the single String value for * * @return the single String value representation for the given value list */ private String createValueFromList(List valueList) { if (valueList == null) { return null; } StringBuffer result = new StringBuffer(valueList.size() * 32); Iterator i = valueList.iterator(); while (i.hasNext()) { result.append( replaceDelimiter(i.next().toString(), VALUE_LIST_DELIMITER, VALUE_LIST_DELIMITER_REPLACEMENT)); if (i.hasNext()) { result.append(VALUE_LIST_DELIMITER); } } return result.toString(); } /** * Returns the single String value representation for the given value map.

* * @param valueMap the value map to create the single String value for * * @return the single String value representation for the given value map */ private String createValueFromMap(Map valueMap) { if (valueMap == null) { return null; } StringBuffer result = new StringBuffer(valueMap.size() * 32); Iterator> i = valueMap.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = i.next(); String key = entry.getKey(); String value = entry.getValue(); key = replaceDelimiter(key, VALUE_LIST_DELIMITER, VALUE_LIST_DELIMITER_REPLACEMENT); key = replaceDelimiter(key, VALUE_MAP_DELIMITER, VALUE_MAP_DELIMITER_REPLACEMENT); value = replaceDelimiter(value, VALUE_LIST_DELIMITER, VALUE_LIST_DELIMITER_REPLACEMENT); value = replaceDelimiter(value, VALUE_MAP_DELIMITER, VALUE_MAP_DELIMITER_REPLACEMENT); result.append(key); result.append(VALUE_MAP_DELIMITER); result.append(value); if (i.hasNext()) { result.append(VALUE_LIST_DELIMITER); } } return result.toString(); } /** * Rebuilds the given delimiter character from the replacement string.

* * @param value the string that is scanned * @param delimiter the delimiter character to rebuild * @param delimiterReplacement the replacement string for the delimiter character * @return the substituted string */ private String rebuildDelimiter(String value, char delimiter, String delimiterReplacement) { return CmsStringUtil.substitute(value, delimiterReplacement, String.valueOf(delimiter)); } /** * Replaces the given delimiter character with the replacement string.

* * @param value the string that is scanned * @param delimiter the delimiter character to replace * @param delimiterReplacement the replacement string for the delimiter character * @return the substituted string */ private String replaceDelimiter(String value, char delimiter, String delimiterReplacement) { return CmsStringUtil.substitute(value, String.valueOf(delimiter), delimiterReplacement); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy