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

org.opencms.jsp.util.CmsJspContentAccessValueWrapper 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.

There is a newer version: 18.0
Show 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, 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.jsp.util;

import org.opencms.ade.contenteditor.CmsContentService;
import org.opencms.file.CmsObject;
import org.opencms.gwt.shared.CmsGwtConstants;
import org.opencms.i18n.CmsLocaleManager;
import org.opencms.util.CmsCollectionsGenericWrapper;
import org.opencms.util.CmsConstantMap;
import org.opencms.util.CmsMacroResolver;
import org.opencms.util.CmsStringUtil;
import org.opencms.xml.CmsXmlUtils;
import org.opencms.xml.I_CmsXmlDocument;
import org.opencms.xml.types.I_CmsXmlContentValue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.collections.Transformer;

import org.dom4j.Node;

/**
 * Allows direct access to XML content values, with possible iteration of sub-nodes.

* * The implementation is optimized for performance and uses lazy initializing of the * requested values as much as possible.

* * @since 7.0.2 * * @see CmsJspContentAccessBean * @see org.opencms.jsp.CmsJspTagContentAccess */ public final class CmsJspContentAccessValueWrapper extends A_CmsJspValueWrapper { /** * Provides a Map with Booleans that * indicate if a nested sub value (xpath) for the current value is available in the XML content.

*/ public class CmsHasValueTransformer implements Transformer { /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ @Override public Object transform(Object input) { return Boolean.valueOf( getContentValue().getDocument().hasValue(createPath(input), getContentValue().getLocale())); } } /** * Provides a Map which lets the user a nested sub value from the current value, * the input is assumed to be a String that represents an xpath in the XML content.

*/ public class CmsRdfaTransformer implements Transformer { /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ @Override public Object transform(Object input) { if (isDirectEditEnabled(obtainCmsObject())) { return CmsContentService.getRdfaAttributes(getContentValue(), String.valueOf(input)); } else { return ""; } } } /** * Provides a Map which lets the user access nested sub value Lists directly below the current value, * the input is assumed to be a String that represents an xpath in the XML content.

*/ public class CmsSubValueListTransformer implements Transformer { /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ @Override public Object transform(Object input) { List values = getContentValue().getDocument().getSubValues( createPath(input), getContentValue().getLocale()); List result = new ArrayList(); Iterator i = values.iterator(); while (i.hasNext()) { // must iterate values from XML content and create wrapper for each I_CmsXmlContentValue value = i.next(); result.add(createWrapper(obtainCmsObject(), value, getContentValue(), value.getName())); } return result; } } /** * Provides a Map which lets the user access nested sub value Lists from the current value, * the input is assumed to be a String that represents an xpath in the XML content.

*/ public class CmsValueListTransformer implements Transformer { /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ @Override public Object transform(Object input) { List values = getContentValue().getDocument().getValues( createPath(input), getContentValue().getLocale()); List result = new ArrayList(); Iterator i = values.iterator(); while (i.hasNext()) { // must iterate values from XML content and create wrapper for each I_CmsXmlContentValue value = i.next(); result.add(createWrapper(obtainCmsObject(), value, getContentValue(), (String)input)); } return result; } } /** * Provides a Map which lets the user a nested sub value from the current value, * the input is assumed to be a String that represents an xpath in the XML content.

*/ public class CmsValueTransformer implements Transformer { /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ @Override public Object transform(Object input) { I_CmsXmlContentValue value = getContentValue().getDocument().getValue( createPath(input), getContentValue().getLocale()); return createWrapper(obtainCmsObject(), value, getContentValue(), (String)input); } } /** * Provides a Map which lets the user directly access sub-nodes of the XML represented by the current value, * the input is assumed to be a String that represents an xpath in the XML content.

*/ public class CmsXmlValueTransformer implements Transformer { /** * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) */ @Override public Object transform(Object input) { Node node = getContentValue().getElement().selectSingleNode(input.toString()); if (node != null) { return node.getStringValue(); } return ""; } } /** * The null value info, used to generate RDFA and DND annotations for null values.

*/ protected static class NullValueInfo { /** The content document. */ private I_CmsXmlDocument m_content; /** The content locale. */ private Locale m_locale; /** The parent value. */ private I_CmsXmlContentValue m_parentValue; /** The value path name. */ private String m_valueName; /** * Constructor.

* * @param parentValue the parent value * @param valueName the value path name */ protected NullValueInfo(I_CmsXmlContentValue parentValue, String valueName) { m_parentValue = parentValue; m_valueName = valueName; } /** * @param content the content document * @param valueName the value path name * @param locale the content locale */ protected NullValueInfo(I_CmsXmlDocument content, String valueName, Locale locale) { m_content = content; m_valueName = valueName; m_locale = locale; } /** * Returns the content.

* * @return the content */ public I_CmsXmlDocument getContent() { return m_content; } /** * Returns the locale.

* * @return the locale */ public Locale getLocale() { return m_locale; } /** * Returns the parent value.

* * @return the parent value */ public I_CmsXmlContentValue getParentValue() { return m_parentValue; } /** * Returns the value name.

* * @return the value name */ public String getValueName() { return m_valueName; } } /** Constant for the null (non existing) value. */ protected static final CmsJspContentAccessValueWrapper NULL_VALUE_WRAPPER = new CmsJspContentAccessValueWrapper(); /** The wrapped OpenCms user context. */ private CmsObject m_cms; /** The wrapped XML content value. */ private I_CmsXmlContentValue m_contentValue; /** Calculated hash code. */ private int m_hashCode; /** The lazy initialized Map that checks if a value is available. */ private Map m_hasValue; /** The macro resolver used to resolve macros for this value. */ private CmsMacroResolver m_macroResolver; /** The names of the sub elements. */ private List m_names; /** The null value info, used to generate RDFA and DND annotations for null values. */ private NullValueInfo m_nullValueInfo; /** The lazy initialized map of RDFA for nested sub values. */ private Map m_rdfa; /** The lazy initialized sub value list Map. */ private Map> m_subValueList; /** The lazy initialized value Map. */ private Map m_value; /** The lazy initialized value list Map. */ private Map> m_valueList; /** The lazy initialized XML element Map. */ private Map m_xml; /** * Private constructor, used for creation of NULL constant value, use factory method to create instances.

* * @see #createWrapper(CmsObject, I_CmsXmlContentValue,I_CmsXmlContentValue,String) */ private CmsJspContentAccessValueWrapper() { // cast needed to avoid compiler confusion with constructors this((CmsObject)null, (I_CmsXmlContentValue)null); } /** * Private constructor, use factory method to create instances.

* * Used to create a copy with macro resolving enabled.

* * @param base the wrapper base * @param macroResolver the macro resolver to use * * @see #createWrapper(CmsObject, I_CmsXmlContentValue,I_CmsXmlContentValue,String) */ private CmsJspContentAccessValueWrapper(CmsJspContentAccessValueWrapper base, CmsMacroResolver macroResolver) { m_cms = base.m_cms; m_contentValue = base.m_contentValue; m_hashCode = base.m_hashCode; m_hasValue = base.m_hasValue; m_macroResolver = macroResolver; m_value = base.m_value; m_valueList = base.m_valueList; } /** * Private constructor, use factory method to create instances.

* * @param cms the current users OpenCms context * @param value the value to warp * * @see #createWrapper(CmsObject, I_CmsXmlContentValue,I_CmsXmlContentValue,String) */ private CmsJspContentAccessValueWrapper(CmsObject cms, I_CmsXmlContentValue value) { // a null value is used for constant generation m_cms = cms; m_contentValue = value; if ((m_contentValue == null) || m_contentValue.isSimpleType()) { // maps must all be static m_hasValue = CmsConstantMap.CONSTANT_BOOLEAN_FALSE_MAP; m_value = CmsJspContentAccessBean.CONSTANT_NULL_VALUE_WRAPPER_MAP; m_valueList = CmsConstantMap.CONSTANT_EMPTY_LIST_MAP; } } /** * Factory method to create a new XML content value wrapper.

* * In case either parameter is null, the {@link #NULL_VALUE_WRAPPER} is returned.

* * @param cms the current users OpenCms context * @param value the value to warp * @param parentValue the parent value, required to set the null value info * @param valueName the value path name * * @return a new content value wrapper instance, or null if any parameter is null */ public static CmsJspContentAccessValueWrapper createWrapper( CmsObject cms, I_CmsXmlContentValue value, I_CmsXmlContentValue parentValue, String valueName) { if ((value != null) && (cms != null)) { return new CmsJspContentAccessValueWrapper(cms, value); } if ((parentValue != null) && (valueName != null) && (cms != null)) { CmsJspContentAccessValueWrapper wrapper = new CmsJspContentAccessValueWrapper(); wrapper.m_nullValueInfo = new NullValueInfo(parentValue, valueName); wrapper.m_cms = cms; return wrapper; } // if no value is available, return NULL_VALUE_WRAPPER; } /** * Factory method to create a new XML content value wrapper.

* * In case either parameter is null, the {@link #NULL_VALUE_WRAPPER} is returned.

* * @param cms the current users OpenCms context * @param value the value to warp * @param content the content document, required to set the null value info * @param valueName the value path name * @param locale the selected locale * * @return a new content value wrapper instance, or null if any parameter is null */ public static CmsJspContentAccessValueWrapper createWrapper( CmsObject cms, I_CmsXmlContentValue value, I_CmsXmlDocument content, String valueName, Locale locale) { if ((value != null) && (cms != null)) { return new CmsJspContentAccessValueWrapper(cms, value); } if ((content != null) && (valueName != null) && (locale != null) && (cms != null)) { CmsJspContentAccessValueWrapper wrapper = new CmsJspContentAccessValueWrapper(); wrapper.m_nullValueInfo = new NullValueInfo(content, valueName, locale); wrapper.m_cms = cms; return wrapper; } // if no value is available, return NULL_VALUE_WRAPPER; } /** * Returns if direct edit is enabled.

* * @param cms the current cms context * * @return true if direct edit is enabled */ static boolean isDirectEditEnabled(CmsObject cms) { return !cms.getRequestContext().getCurrentProject().isOnlineProject() && (cms.getRequestContext().getAttribute(CmsGwtConstants.PARAM_DISABLE_DIRECT_EDIT) == null); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof CmsJspContentAccessValueWrapper) { // rely on hash code implementation for equals method return hashCode() == ((CmsJspContentAccessValueWrapper)obj).hashCode(); } return false; } /** * Returns the wrapped content value.

* * Note that this will return null when {@link #getExists()} returns false

. * * @return the wrapped content value */ public I_CmsXmlContentValue getContentValue() { return m_contentValue; } /** * Returns true in case this value actually exists in the XML content it was requested from.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:if test="${content.value['Link'].exists}" >
     *         The content has a "Link" value!
     *     </c:if>
     * </cms:contentload>
* * @return true in case this value actually exists in the XML content it was requested from */ @Override public boolean getExists() { return m_contentValue != null; } /** * Returns a lazy initialized Map that provides Booleans that * indicate if a nested sub value (xpath) for the current value is available in the XML content.

* * The provided Map key is assumed to be a String that represents the relative xpath to the value.

* * In case the current value is not a nested XML content value, or the XML content value does not exist, * the {@link CmsConstantMap#CONSTANT_BOOLEAN_FALSE_MAP} is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:if test="${content.value['Link'].hasValue['Description']}" >
     *         The content has a "Description" value as sub element to the "Link" value!
     *     </c:if>
     * </cms:contentload>
* * Please note that you can also test if a sub-value exists like this:
     * <c:if test="${content.value['Link'].value['Description'].exists}" > ... </c:if>
* * @return a lazy initialized Map that provides Booleans that * indicate if a sub value (xpath) for the current value is available in the XML content */ public Map getHasValue() { if (m_hasValue == null) { m_hasValue = CmsCollectionsGenericWrapper.createLazyMap(new CmsHasValueTransformer()); } return m_hasValue; } /** * Returns the annotation that enables image drag and drop for this content value.

* * Use to insert the annotation attributes into a HTML tag.

* * Only makes sense in case this node actually contains the path to an image.

* * Example using EL: <span ${value.Image.imageDndAttr}> ... </span> will result in * <span data-imagednd="..."> ... </span>

* * @return the annotation that enables image drag and drop for this content value */ public String getImageDndAttr() { String result = ""; CmsObject cms = obtainCmsObject(); if ((cms != null) && (m_contentValue != null) && isDirectEditEnabled(cms) && (m_contentValue.getDocument().getFile() != null)) { result = CmsJspContentAccessBean.createImageDndAttr( m_contentValue.getDocument().getFile().getStructureId(), m_contentValue.getPath(), String.valueOf(m_contentValue.getLocale())); } return result; } /** * Returns the node index of the XML content value in the source XML document, * starting with 0.

* * In case the XML content value does not exist, -1 is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     The locale of the Link node: ${content.value['Link'].locale}
     * </cms:contentload>
* * @return the locale of the current XML content value */ public int getIndex() { if (m_contentValue == null) { return -1; } return m_contentValue.getIndex(); } /** * Returns true in case the value is empty, that is either null or an empty String.

* * In case the XML content value does not exist, true is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:if test="${content.value['Link'].isEmpty}" >
     *         The content of the "Link" value is empty.
     *     </c:if>
     * </cms:contentload>
* * @return true in case the value is empty */ @Override public boolean getIsEmpty() { if (m_contentValue == null) { // this is the case for non existing values return true; } if (m_contentValue.isSimpleType()) { // return values for simple type return CmsStringUtil.isEmpty(m_contentValue.getStringValue(m_cms)); } else { // nested types are not empty if they have any children in the XML return m_contentValue.getElement().elements().size() > 0; } } /** * Returns true in case the value is empty or whitespace only, * that is either null or String that contains only whitespace chars.

* * In case the XML content value does not exist, true is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:if test="${content.value['Link'].isEmptyOrWhitespaceOnly}" >
     *         The content of the "Link" value is empty or contains only whitespace chars.
     *     </c:if>
     * </cms:contentload>
* * @return true in case the value is empty or whitespace only */ @Override public boolean getIsEmptyOrWhitespaceOnly() { if (m_contentValue == null) { // this is the case for non existing values return true; } if (m_contentValue.isSimpleType()) { // return values for simple type return CmsStringUtil.isEmptyOrWhitespaceOnly(m_contentValue.getStringValue(m_cms)); } else { // nested types are not empty if they have any children in the XML return m_contentValue.getElement().elements().isEmpty(); } } /** * Returns true in case the value is set in the content, * i.e. the value exists and is not empty or whitespace only.

* * In case the XML content value does exist and has a non empty value, true is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:if test="${content.value['Link'].isSet}" >
     *         The content of the "Link" value is not empty.
     *     </c:if>
     * </cms:contentload>
* * @return true in case the value is set */ @Override public boolean getIsSet() { return !getIsEmptyOrWhitespaceOnly(); } /** * Returns the Locale of the current XML content value.

* * In case the XML content value does not exist, the OpenCms system default Locale is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     The locale of the Link node: ${content.value['Link'].locale}
     * </cms:contentload>
* * @return the locale of the current XML content value */ public Locale getLocale() { if (m_contentValue == null) { return CmsLocaleManager.getDefaultLocale(); } return m_contentValue.getLocale(); } /** * Returns the xml node name of the wrapped content value.

* * @return the xml node name * * @see org.opencms.xml.types.I_CmsXmlSchemaType#getName() */ public String getName() { if (m_contentValue == null) { return null; } return m_contentValue.getName(); } /** * Returns a list that provides the names of all nested sub values * directly below the current value from the XML content, including the index.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:forEach items="${content.value['Items'].names}" var="elem">
     *         <c:out value="${elem}" />
     *     </c:forEach>
     * </cms:contentload>
* * @return a list with all available elements paths (Strings) available directly below this element */ public List getNames() { if ((m_names == null)) { m_names = new ArrayList(); if (!m_contentValue.isSimpleType()) { for (I_CmsXmlContentValue value : m_contentValue.getDocument().getSubValues(getPath(), getLocale())) { m_names.add(CmsXmlUtils.createXpathElement(value.getName(), value.getXmlIndex() + 1)); } } } return m_names; } /** * Returns the path to the current XML content value.

* * In case the XML content value does not exist, an empty String "" is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     The path to the Link node in the XML: ${content.value['Link'].path}
     * </cms:contentload>
* * @return the path to the current XML content value */ public String getPath() { if (m_contentValue == null) { return ""; } return m_contentValue.getPath(); } /** * Returns a lazy initialized Map that provides the RDFA for nested sub values.

* * The provided Map key is assumed to be a String that represents the relative xpath to the value.

* * @return a lazy initialized Map that provides the RDFA for nested sub values */ public Map getRdfa() { if (m_rdfa == null) { m_rdfa = CmsCollectionsGenericWrapper.createLazyMap(new CmsRdfaTransformer()); } return m_rdfa; } /** * Returns the RDF annotation to this content value.

* * Use to insert the annotation attributes into a HTML tag.

* Example using EL: <h1 ${value.Title.rdfaAttr}>${value.Title}</h1> will result in * <h1 about="..." property="...">My title</h1>

* * @return the RDFA */ public String getRdfaAttr() { String result = ""; CmsObject cms = obtainCmsObject(); if (cms != null) { if (isDirectEditEnabled(cms)) { if (m_contentValue != null) { // within the offline project return the OpenCms specific entity id's and property names result = CmsContentService.getRdfaAttributes(m_contentValue); } else if ((m_nullValueInfo != null)) { if (m_nullValueInfo.getParentValue() != null) { result = CmsContentService.getRdfaAttributes( m_nullValueInfo.getParentValue(), m_nullValueInfo.getValueName()); } else if (m_nullValueInfo.getContent() != null) { result = CmsContentService.getRdfaAttributes( m_nullValueInfo.getContent(), m_nullValueInfo.getLocale(), m_nullValueInfo.getValueName()); } } } else { // TODO: return mapped property names etc. when online } } return result; } /** * Short form of {@link #getResolveMacros()}.

* * @return a value wrapper with macro resolving turned on * * @see #getResolveMacros() */ public CmsJspContentAccessValueWrapper getResolve() { return getResolveMacros(); } /** * Turn on macro resolving for the wrapped value.

* * Macro resolving is turned off by default. * When turned on, a macro resolver is initialized with * the current OpenCms user context and the URI of the current resource. * This means known macros contained in the wrapped value will be resolved when the output String is generated. * For example, a %(property.Title) in the value would be replaced with the * value of the title property. Macros that can not be resolved will be kept.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     The text with macros resolved: ${content.value['Text'].resolveMacros}
     * </cms:contentload>
* * @return a value wrapper with macro resolving turned on * * @see CmsMacroResolver */ public CmsJspContentAccessValueWrapper getResolveMacros() { if (m_macroResolver == null) { CmsMacroResolver macroResolver = CmsMacroResolver.newInstance(); macroResolver.setCmsObject(m_cms); macroResolver.setKeepEmptyMacros(true); return new CmsJspContentAccessValueWrapper(this, macroResolver); } // macro resolving is already turned on return this; } /** * Returns the String value of the wrapped content value.

* * Note that this will return the empty String "" when {@link #getExists()} returns false

. * * @return the String value of the wrapped content value * * @see #toString() */ public String getStringValue() { return toString(); } /** * Returns a lazy initialized Map that provides the Lists of sub values directly below * the current value from the XML content.

* * The provided Map key is assumed to be a String that represents the relative xpath to the value. * Use this method in case you want to iterate over a List of sub values from the XML content.

* * In case the current value is not a nested XML content value, or the XML content value does not exist, * the {@link CmsConstantMap#CONSTANT_EMPTY_LIST_MAP} is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:forEach var="desc" items="${content.value['Link'].subValueList['Description']}">
     *         ${desc}
     *     </c:forEach>
     * </cms:contentload>
* * @return a lazy initialized Map that provides a Lists of direct sub values of the current value from the XML content */ public Map> getSubValueList() { if (m_subValueList == null) { m_subValueList = CmsCollectionsGenericWrapper.createLazyMap(new CmsSubValueListTransformer()); } return m_subValueList; } /** * Returns the schema type name of the wrapped content value.

* * @return the type name * * @see org.opencms.xml.types.I_CmsXmlSchemaType#getTypeName() */ public String getTypeName() { if (m_contentValue != null) { return m_contentValue.getTypeName(); } return null; } /** * Returns a lazy initialized Map that provides the nested sub values * for the current value from the XML content.

* * The provided Map key is assumed to be a String that represents the relative xpath to the value.

* * In case the current value is not a nested XML content value, or the XML content value does not exist, * the {@link CmsJspContentAccessBean#CONSTANT_NULL_VALUE_WRAPPER_MAP} is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     The Link Description: ${content.value['Link'].value['Description']}
     * </cms:contentload>
* * Please note that this example will only work if the 'Link' element is mandatory in the schema definition * of the XML content.

* * @return a lazy initialized Map that provides a sub value for the current value from the XML content */ public Map getValue() { if (m_value == null) { m_value = CmsCollectionsGenericWrapper.createLazyMap(new CmsValueTransformer()); } return m_value; } /** * Returns a lazy initialized Map that provides the Lists of nested sub values * for the current value from the XML content.

* * The provided Map key is assumed to be a String that represents the relative xpath to the value. * Use this method in case you want to iterate over a List of values form the XML content.

* * In case the current value is not a nested XML content value, or the XML content value does not exist, * the {@link CmsConstantMap#CONSTANT_EMPTY_LIST_MAP} is returned.

* * Usage example on a JSP with the JSTL:

     * <cms:contentload ... >
     *     <cms:contentaccess var="content" />
     *     <c:forEach var="desc" items="${content.value['Link'].valueList['Description']}">
     *         ${desc}
     *     </c:forEach>
     * </cms:contentload>
* * @return a lazy initialized Map that provides a Lists of sub values for the current value from the XML content */ public Map> getValueList() { if (m_valueList == null) { m_valueList = CmsCollectionsGenericWrapper.createLazyMap(new CmsValueListTransformer()); } return m_valueList; } /** * Returns a lazy initialized Map that provides direct access to the XML element * for the current value from the XML content.

* * @return a lazy initialized Map that provides direct access to the XML element for the current value from the XML content */ public Map getXmlText() { if (m_xml == null) { m_xml = CmsCollectionsGenericWrapper.createLazyMap(new CmsXmlValueTransformer()); } return m_xml; } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { if (m_contentValue == null) { return 0; } if (m_hashCode == 0) { StringBuffer result = new StringBuffer(64); result.append(m_contentValue.getDocument().getFile().getStructureId().toString()); result.append('/'); result.append(m_contentValue.getLocale()); result.append('/'); result.append(m_contentValue.getPath()); m_hashCode = result.toString().hashCode(); } return m_hashCode; } /** * Returns the wrapped OpenCms user context.

* * Note that this will return null when {@link #getExists()} returns false. * * @return the wrapped OpenCms user context */ public CmsObject obtainCmsObject() { return m_cms; } /** * Returns the wrapped content value.

* * Note that this will return null when {@link #getExists()} returns false

. * * Method name does not start with "get" to prevent using it in the expression language.

* * @return the wrapped content value * * @deprecated use {@link #getContentValue()} instead */ @Deprecated public I_CmsXmlContentValue obtainContentValue() { return m_contentValue; } /** * @see java.lang.Object#toString() * @see #getStringValue() */ @Override public String toString() { if (m_contentValue == null) { // this is the case for non existing values return ""; } if (m_contentValue.isSimpleType()) { // return values for simple type String value = m_contentValue.getStringValue(m_cms); if (m_macroResolver == null) { // no macro resolving return value; } else { // resolve macros first return m_macroResolver.resolveMacros(value); } } else { // nested types should not be called this way by the user return ""; } } /** * Returns the path to the XML content based on the current element path.

* * This is used to create xpath information for sub-elements in the transformers.

* * @param input the additional path that is appended to the current path * * @return the path to the XML content based on the current element path */ protected String createPath(Object input) { return CmsXmlUtils.concatXpath(m_contentValue.getPath(), String.valueOf(input)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy