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.i18n.CmsLocaleManager;
031import org.opencms.i18n.CmsMessageContainer;
032import org.opencms.main.OpenCms;
033import org.opencms.util.CmsStringUtil;
034import org.opencms.xml.CmsXmlUtils;
035import org.opencms.xml.I_CmsXmlDocument;
036
037import java.util.Locale;
038
039import javax.servlet.jsp.JspException;
040import javax.servlet.jsp.JspTagException;
041import javax.servlet.jsp.tagext.Tag;
042import javax.servlet.jsp.tagext.TagSupport;
043
044/**
045 * Used to check the availablity of an XML content item for conditional display.<p>
046 *
047 * @since 6.0.0
048 */
049public class CmsJspTagContentCheck extends TagSupport {
050
051    /** Serial version UID required for safe serialization. */
052    private static final long serialVersionUID = -5996702196453747182L;
053
054    /** Condition for element check. */
055    private boolean m_checkall;
056
057    /** Condition for negative element check. */
058    private boolean m_checknone;
059
060    /** The list of element to check. */
061    private String m_elementList;
062
063    /** The locale to check for. */
064    private Locale m_locale;
065
066    /**
067     * Internal action method to check the elements from the provided XML content item.<p>
068     *
069     * @param elementList the list of elements to check for
070     * @param prefix the Xpath prefix to append the elements to (in case of nested schemas)
071     * @param checkall flag to indicate that all elements should be checked
072     * @param checknone flag to indicate that the check is done for nonexisting elements
073     * @param content the XML content document to check the elements from
074     * @param locale the locale to check the element for
075     *
076     * @return true if the test succeeds, false if the test fails
077     */
078    public static boolean contentCheckTagAction(
079        String elementList,
080        String prefix,
081        boolean checkall,
082        boolean checknone,
083        I_CmsXmlDocument content,
084        Locale locale) {
085
086        boolean found = false;
087        String[] elements = CmsStringUtil.splitAsArray(elementList, ',');
088        for (int i = (elements.length - 1); i >= 0; i--) {
089
090            String element = CmsXmlUtils.concatXpath(prefix, elements[i].trim());
091            found = found || content.hasValue(element, locale);
092
093            if (found && checknone) {
094                // found an item that must not exist
095                return false;
096            }
097            if (found && !checkall && !checknone) {
098                // we need to find only one item
099                return true;
100            }
101        }
102
103        if (!found && checknone) {
104            // no item found as expected
105            return true;
106        }
107
108        return found;
109    }
110
111    /**
112     * @see javax.servlet.jsp.tagext.Tag#doEndTag()
113     */
114    @Override
115    public int doEndTag() {
116
117        if (OpenCms.getSystemInfo().getServletContainerSettings().isReleaseTagsAfterEnd()) {
118            // need to release manually, JSP container may not call release as required (happens with Tomcat)
119            release();
120        }
121        return EVAL_PAGE;
122    }
123
124    /**
125     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
126     */
127    @Override
128    public int doStartTag() throws JspException {
129
130        // get a reference to the parent "content load" class
131        Tag ancestor = findAncestorWithClass(this, I_CmsXmlContentContainer.class);
132        if (ancestor == null) {
133            CmsMessageContainer errMsgContainer = Messages.get().container(
134                Messages.ERR_TAG_CONTENTCHECK_WRONG_PARENT_0);
135            String msg = Messages.getLocalizedMessage(errMsgContainer, pageContext);
136            throw new JspTagException(msg);
137        }
138        I_CmsXmlContentContainer contentContainer = (I_CmsXmlContentContainer)ancestor;
139        String prefix = contentContainer.getXmlDocumentElement();
140
141        // get loaded content from parent <contentload> tag
142        I_CmsXmlDocument content = contentContainer.getXmlDocument();
143
144        if (m_locale == null) {
145            m_locale = contentContainer.getXmlDocumentLocale();
146        }
147
148        // calculate the result
149        boolean result = contentCheckTagAction(m_elementList, prefix, m_checkall, m_checknone, content, m_locale);
150
151        if (result) {
152            return EVAL_BODY_INCLUDE;
153        } else {
154            return SKIP_BODY;
155        }
156    }
157
158    /**
159     * Returns the list of elements to check.<p>
160     *
161     * @return the list of elements to check
162     */
163    public String getIfexists() {
164
165        return m_elementList != null ? m_elementList : "";
166    }
167
168    /**
169     * Returns the list of elements to check.<p>
170     *
171     * @return the list of elements to check
172     */
173    public String getIfexistsall() {
174
175        return m_elementList != null ? m_elementList : "";
176    }
177
178    /**
179     * Returns the list of elements to check.<p>
180     *
181     * @return the list of elements to check
182     */
183    public String getIfexistsnone() {
184
185        return m_elementList != null ? m_elementList : "";
186    }
187
188    /**
189     * Returns the list of elements to check.<p>
190     *
191     * @return the list of elements to check
192     */
193    public String getIfexistsone() {
194
195        return m_elementList != null ? m_elementList : "";
196    }
197
198    /**
199     * Returns the locale used for checking.<p>
200     *
201     * @return the locale used for checking
202     */
203    public String getLocale() {
204
205        return (m_locale != null) ? m_locale.toString() : "";
206    }
207
208    /**
209     * @see javax.servlet.jsp.tagext.Tag#release()
210     */
211    @Override
212    public void release() {
213
214        m_checkall = false;
215        m_checknone = false;
216        m_elementList = null;
217        m_locale = null;
218        super.release();
219    }
220
221    /**
222     * Sets the list of elements to check for.<p>
223     *
224     * @param elementList the list of elements to check for
225     */
226    public void setIfexists(String elementList) {
227
228        if (elementList != null) {
229            m_elementList = elementList;
230            m_checkall = false;
231            m_checknone = false;
232        }
233    }
234
235    /**
236     * Sets the list of elements to check for.<p>
237     *
238     * @param elementList the list of elements to check for
239     */
240    public void setIfexistsall(String elementList) {
241
242        if (elementList != null) {
243            m_elementList = elementList;
244            m_checkall = true;
245            m_checknone = false;
246        }
247    }
248
249    /**
250     * Sets the list of elements to check for.<p>
251     *
252     * @param elementList the list of elements to check for
253     */
254    public void setIfexistsnone(String elementList) {
255
256        if (elementList != null) {
257            m_elementList = elementList;
258            m_checkall = false;
259            m_checknone = true;
260        }
261    }
262
263    /**
264     * Sets the list of elements to check for.<p>
265     *
266     * @param elementList the list of elements to check for
267     */
268    public void setIfexistsone(String elementList) {
269
270        if (elementList != null) {
271            m_elementList = elementList;
272            m_checkall = false;
273            m_checknone = false;
274        }
275    }
276
277    /**
278     * Sets the locale used for checking.<p>
279     *
280     * @param locale the locale to set
281     */
282    public void setLocale(String locale) {
283
284        if (CmsStringUtil.isEmpty(locale)) {
285            m_locale = null;
286        } else {
287            m_locale = CmsLocaleManager.getLocale(locale);
288        }
289    }
290}