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 GmbH & Co. KG, 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.jsp; 029 030import org.opencms.file.CmsResource; 031import org.opencms.i18n.CmsMessageContainer; 032import org.opencms.xml.CmsXmlUtils; 033import org.opencms.xml.I_CmsXmlDocument; 034 035import java.util.List; 036import java.util.Locale; 037 038import javax.servlet.jsp.JspException; 039import javax.servlet.jsp.JspTagException; 040import javax.servlet.jsp.tagext.Tag; 041import javax.servlet.jsp.tagext.TagSupport; 042 043/** 044 * Used to loop through the element values of an XML content item.<p> 045 * 046 * @since 6.0.0 047 */ 048public class CmsJspTagContentLoop extends TagSupport implements I_CmsXmlContentContainer { 049 050 /** Serial version UID required for safe serialization. */ 051 private static final long serialVersionUID = 8832749526732064836L; 052 053 /** Reference to the parent 'contentload' tag. */ 054 private transient I_CmsXmlContentContainer m_container; 055 056 /** Reference to the looped content element. */ 057 private transient I_CmsXmlDocument m_content; 058 059 /** Name of the current element (including the index). */ 060 private String m_currentElement; 061 062 /** Name of the content node element to show. */ 063 private String m_element; 064 065 /** Indicates if this is the first content iteration loop. */ 066 private boolean m_firstLoop; 067 068 /** Index of the content node element to show. */ 069 private int m_index = -1; 070 071 /** Reference to the currently selected locale. */ 072 private Locale m_locale; 073 074 /** 075 * Empty constructor, required for JSP tags.<p> 076 */ 077 public CmsJspTagContentLoop() { 078 079 super(); 080 } 081 082 /** 083 * Constructor used when using <code>contentloop</code> from scriptlet code.<p> 084 * 085 * @param container the parent content container that provides the content element to loop 086 * @param element the element to loop in the content 087 */ 088 public CmsJspTagContentLoop(I_CmsXmlContentContainer container, String element) { 089 090 m_element = element; 091 init(container); 092 } 093 094 /** 095 * @see javax.servlet.jsp.tagext.TagSupport#doAfterBody() 096 */ 097 @Override 098 public int doAfterBody() { 099 100 if (hasMoreResources()) { 101 // one more element with the same name is available, loop again 102 return EVAL_BODY_AGAIN; 103 } 104 // no more elements with this name available, finish the loop 105 return SKIP_BODY; 106 } 107 108 /** 109 * @see javax.servlet.jsp.tagext.Tag#doEndTag() 110 */ 111 @Override 112 public int doEndTag() { 113 114 release(); 115 return EVAL_PAGE; 116 } 117 118 /** 119 * @see javax.servlet.jsp.tagext.Tag#doStartTag() 120 */ 121 @Override 122 public int doStartTag() throws JspException { 123 124 // get a reference to the parent "content container" class 125 Tag ancestor = findAncestorWithClass(this, I_CmsXmlContentContainer.class); 126 if (ancestor == null) { 127 CmsMessageContainer errMsgContainer = Messages.get().container( 128 Messages.ERR_PARENTLESS_TAG_1, 129 "contentloop"); 130 String msg = Messages.getLocalizedMessage(errMsgContainer, pageContext); 131 throw new JspTagException(msg); 132 } 133 I_CmsXmlContentContainer container = (I_CmsXmlContentContainer)ancestor; 134 135 // initialize the content 136 init(container); 137 138 if (hasMoreResources()) { 139 // selected element is available at last once in content 140 return EVAL_BODY_INCLUDE; 141 } else { 142 // no value available for the selected element name, so we skip the whole body 143 return SKIP_BODY; 144 } 145 } 146 147 /** 148 * @see org.opencms.jsp.I_CmsXmlContentContainer#getCollectorName() 149 */ 150 public String getCollectorName() { 151 152 return m_container.getCollectorName(); 153 } 154 155 /** 156 * @see org.opencms.jsp.I_CmsXmlContentContainer#getCollectorParam() 157 */ 158 public String getCollectorParam() { 159 160 return m_container.getCollectorParam(); 161 } 162 163 /** 164 * @see org.opencms.jsp.I_CmsXmlContentContainer#getCollectorResult() 165 */ 166 public List<CmsResource> getCollectorResult() { 167 168 return m_container.getCollectorResult(); 169 } 170 171 /** 172 * Returns the name of the content node element to show.<p> 173 * 174 * @return the name of the content node element to show 175 */ 176 public String getElement() { 177 178 return (m_element != null) ? m_element : ""; 179 } 180 181 /** 182 * @see org.opencms.jsp.I_CmsResourceContainer#getResource() 183 */ 184 public CmsResource getResource() { 185 186 return m_content.getFile(); 187 } 188 189 /** 190 * @see org.opencms.jsp.I_CmsXmlContentContainer#getResourceName() 191 */ 192 public String getResourceName() { 193 194 return m_container.getResourceName(); 195 } 196 197 /** 198 * @see org.opencms.jsp.I_CmsXmlContentContainer#getXmlDocument() 199 */ 200 public I_CmsXmlDocument getXmlDocument() { 201 202 return m_content; 203 } 204 205 /** 206 * @see org.opencms.jsp.I_CmsXmlContentContainer#getXmlDocumentElement() 207 */ 208 public String getXmlDocumentElement() { 209 210 return m_currentElement; 211 } 212 213 /** 214 * @see org.opencms.jsp.I_CmsXmlContentContainer#getXmlDocumentLocale() 215 */ 216 public Locale getXmlDocumentLocale() { 217 218 return m_locale; 219 } 220 221 /** 222 * @see org.opencms.jsp.I_CmsResourceContainer#hasMoreContent() 223 */ 224 @Deprecated 225 public boolean hasMoreContent() { 226 227 return hasMoreResources(); 228 } 229 230 /** 231 * @see org.opencms.jsp.I_CmsXmlContentContainer#hasMoreResources() 232 */ 233 public boolean hasMoreResources() { 234 235 if (m_firstLoop) { 236 m_firstLoop = false; 237 } else { 238 m_index++; 239 } 240 if (m_content.hasValue(m_element, m_locale, m_index)) { 241 m_currentElement = CmsXmlUtils.createXpath(m_element, m_index + 1); 242 // one more element with the same name is available, loop again 243 return true; 244 } else { 245 // no more elements with this name available, finish the loop 246 return false; 247 } 248 } 249 250 /** 251 * @see org.opencms.jsp.I_CmsXmlContentContainer#isPreloader() 252 */ 253 public boolean isPreloader() { 254 255 return m_container.isPreloader(); 256 } 257 258 /** 259 * @see javax.servlet.jsp.tagext.Tag#release() 260 */ 261 @Override 262 public void release() { 263 264 m_element = null; 265 m_currentElement = null; 266 m_content = null; 267 m_locale = null; 268 m_container = null; 269 m_index = 0; 270 super.release(); 271 } 272 273 /** 274 * Sets the name of the content node element to show.<p> 275 * 276 * @param element the name of the content node element to show 277 */ 278 public void setElement(String element) { 279 280 m_element = element; 281 } 282 283 /** 284 * Initializes this content loop tag.<p> 285 * 286 * @param container the parent content container that provides the content element to loop 287 */ 288 protected void init(I_CmsXmlContentContainer container) { 289 290 m_container = container; 291 292 // append to parent element name (required for nested schemas) 293 m_element = CmsXmlUtils.concatXpath(m_container.getXmlDocumentElement(), m_element); 294 295 // get loaded content from parent <contentload> tag 296 m_content = m_container.getXmlDocument(); 297 m_locale = m_container.getXmlDocumentLocale(); 298 m_index = 0; 299 m_currentElement = null; 300 301 // the next loop is the first loop 302 m_firstLoop = true; 303 } 304}