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.decorator;
029
030import org.opencms.file.CmsFile;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsResource;
033import org.opencms.i18n.CmsLocaleManager;
034import org.opencms.main.CmsException;
035import org.opencms.xml.content.CmsXmlContent;
036import org.opencms.xml.content.CmsXmlContentFactory;
037
038import java.util.ArrayList;
039import java.util.List;
040import java.util.Locale;
041
042import org.htmlparser.Tag;
043
044/**
045 * The CmsDecoratorConfiguration initalizes and stores the text decorations.<p>
046 *
047 * It uses uses the information of one or more <code>{@link CmsDecorationDefintion}</code> to create the
048 * pre- and postfixs for text decorations.
049 *
050 * @since 6.1.3
051 */
052
053public class CmsDecoratorConfiguration implements I_CmsDecoratorConfiguration {
054
055    /** The xpath for the decoration configuration. */
056    public static final String XPATH_DECORATION = "decoration";
057
058    /** The xpath for the exclude configuration. */
059    public static final String XPATH_EXCLUDE = "exclude";
060
061    /** The xpath for the exclude configuration. */
062    public static final String XPATH_EXCLUDEATTR = "excludeattr";
063
064    /** The xpath for the uselocale configuration. */
065    public static final String XPATH_USELOCALE = "uselocale";
066
067    /** The xpath for the filename configuration. */
068    private static final String XPATH_FILENAME = "filename";
069
070    /** The xpath for the markfirst configuration. */
071    private static final String XPATH_MARKFIRST = "markfirst";
072
073    /** The xpath for the name configuration. */
074    private static final String XPATH_NAME = "name";
075
076    /** The xpath for the posttext configuration. */
077    private static final String XPATH_POSTTEXT = "posttext";
078
079    /** The xpath for the posttextfirst configuration. */
080    private static final String XPATH_POSTTEXTFIRST = "posttextfirst";
081
082    /** The xpath for the pretext configuration. */
083    private static final String XPATH_PRETEXT = "pretext";
084
085    /** The xpath for the pretextfirst configuration. */
086    private static final String XPATH_PRETEXTFIRST = "pretextfirst";
087
088    /** The CmsObject. */
089    private CmsObject m_cms;
090
091    /** The config file. */
092    private String m_configFile;
093
094    /** The locale for extracting the configuration data. */
095    private Locale m_configurationLocale = CmsLocaleManager.getLocale("en");
096
097    /** Map of configured decorations. */
098    private CmsDecorationBundle m_decorations;
099
100    /** The list of excluded tags. */
101    private List<String> m_excludes;
102
103    /** The list of excluded attributes. */
104    private List<String> m_excludeattr;
105
106    /** The locale for to build the configuration for. */
107    private Locale m_locale;
108
109    /** The list of already used  decorations. */
110    private List<String> m_usedDecorations;
111
112    /** The list with all <code>{@link CmsDecorationDefintion}</code> instances parsed from the config file. */
113    private List<CmsDecorationDefintion> m_decorationDefinitions;
114
115    /**
116     * Constructor, creates a new, empty CmsDecoratorConfiguration.<p>
117     *
118     */
119    public CmsDecoratorConfiguration() {
120
121        m_decorations = new CmsDecorationBundle();
122        m_configFile = null;
123        m_cms = null;
124        m_locale = null;
125        m_usedDecorations = new ArrayList<String>();
126        m_excludes = new ArrayList<String>();
127        m_excludeattr = new ArrayList<String>();
128        m_decorationDefinitions = new ArrayList<CmsDecorationDefintion>();
129    }
130
131    /**
132     * Constructor, creates a new, empty CmsDecoratorConfiguration.<p>
133     *
134     * @param cms the CmsObject
135     * @throws CmsException if something goes wrong
136     *
137     */
138    public CmsDecoratorConfiguration(CmsObject cms)
139    throws CmsException {
140
141        m_decorations = new CmsDecorationBundle();
142        m_configFile = null;
143        m_cms = cms;
144        m_locale = m_cms.getRequestContext().getLocale();
145        m_usedDecorations = new ArrayList<String>();
146        m_excludes = new ArrayList<String>();
147        m_excludeattr = new ArrayList<String>();
148        m_decorationDefinitions = new ArrayList<CmsDecorationDefintion>();
149        init(cms, null, null);
150    }
151
152    /**
153     * Constructor, creates a new, CmsDecoratorConfiguration with a given config file.<p>
154     *
155     * @param cms the CmsObject
156     * @param configFile the configuration file
157     * @throws CmsException if something goes wrong
158     */
159    public CmsDecoratorConfiguration(CmsObject cms, String configFile)
160    throws CmsException {
161
162        m_decorations = new CmsDecorationBundle();
163        m_configFile = null;
164        m_cms = cms;
165        m_locale = m_cms.getRequestContext().getLocale();
166        m_usedDecorations = new ArrayList<String>();
167        m_excludes = new ArrayList<String>();
168        m_excludeattr = new ArrayList<String>();
169        m_decorationDefinitions = new ArrayList<CmsDecorationDefintion>();
170        init(cms, configFile, null);
171    }
172
173    /**
174     * Constructor, creates a new, CmsDecoratorConfiguration with a given config file and locale.<p>
175     *
176     * @param cms the CmsObject
177     * @param configFile the configuration file
178     * @param locale to locale to build this configuration for
179     * @throws CmsException if something goes wrong
180     */
181    public CmsDecoratorConfiguration(CmsObject cms, String configFile, Locale locale)
182    throws CmsException {
183
184        m_decorations = new CmsDecorationBundle();
185        m_configFile = null;
186        m_cms = cms;
187        m_locale = m_cms.getRequestContext().getLocale();
188        m_usedDecorations = new ArrayList<String>();
189        m_excludes = new ArrayList<String>();
190        m_excludeattr = new ArrayList<String>();
191        m_decorationDefinitions = new ArrayList<CmsDecorationDefintion>();
192        init(cms, configFile, locale);
193    }
194
195    /**
196     * Adds decorations defined in a <code>{@link CmsDecorationDefintion}</code> object to the map of all decorations.<p>
197     * @param decorationDefinition the <code>{@link CmsDecorationDefintion}</code> the decorations to be added
198     * @throws CmsException if something goes wrong
199     */
200    public void addDecorations(CmsDecorationDefintion decorationDefinition) throws CmsException {
201
202        m_decorations.putAll(decorationDefinition.createDecorationBundle(m_cms, m_configurationLocale).getAll());
203    }
204
205    /**
206     * Returns the cms.<p>
207     *
208     * @return the cms
209     */
210    public CmsObject getCms() {
211
212        return m_cms;
213    }
214
215    /**
216     * Returns the configFile.<p>
217     *
218     * @return the configFile
219     */
220    public String getConfigFile() {
221
222        return m_configFile;
223    }
224
225    /**
226     * Returns the configurationLocale.<p>
227     *
228     * @return the configurationLocale
229     */
230    public Locale getConfigurationLocale() {
231
232        return m_configurationLocale;
233    }
234
235    /**
236     * Builds a CmsDecorationDefintion from a given configuration file.<p>
237     *
238     * @param configuration the configuration file
239     * @param i the number of the decoration definition to create
240     * @return CmsDecorationDefintion created form configuration file
241     */
242    public CmsDecorationDefintion getDecorationDefinition(CmsXmlContent configuration, int i) {
243
244        CmsDecorationDefintion decDef = new CmsDecorationDefintion();
245        String name = configuration.getValue(XPATH_DECORATION + "[" + i + "]/" + XPATH_NAME, m_configurationLocale).getStringValue(
246            m_cms);
247        String markfirst = configuration.getValue(
248            XPATH_DECORATION + "[" + i + "]/" + XPATH_MARKFIRST,
249            m_configurationLocale).getStringValue(m_cms);
250        String pretext = configuration.getValue(
251            XPATH_DECORATION + "[" + i + "]/" + XPATH_PRETEXT,
252            m_configurationLocale).getStringValue(m_cms);
253        String posttext = configuration.getValue(
254            XPATH_DECORATION + "[" + i + "]/" + XPATH_POSTTEXT,
255            m_configurationLocale).getStringValue(m_cms);
256        String pretextfirst = configuration.getValue(
257            XPATH_DECORATION + "[" + i + "]/" + XPATH_PRETEXTFIRST,
258            m_configurationLocale).getStringValue(m_cms);
259        String posttextfirst = configuration.getValue(
260            XPATH_DECORATION + "[" + i + "]/" + XPATH_POSTTEXTFIRST,
261            m_configurationLocale).getStringValue(m_cms);
262        String filenname = configuration.getValue(
263            XPATH_DECORATION + "[" + i + "]/" + XPATH_FILENAME,
264            m_configurationLocale).getStringValue(m_cms);
265
266        decDef.setName(name);
267        decDef.setMarkFirst(markfirst.equals("true"));
268        decDef.setPreText(pretext);
269        decDef.setPostText(posttext);
270        decDef.setPreTextFirst(pretextfirst);
271        decDef.setPostTextFirst(posttextfirst);
272        decDef.setConfigurationFile(filenname);
273
274        return decDef;
275    }
276
277    /**
278     * Returns the list with all <code>{@link CmsDecorationDefintion}</code>
279     * instances parsed from the config file.<p>
280     *
281     * @return The list with all <code>{@link CmsDecorationDefintion}</code> instances
282     *      parsed from the config file
283     */
284    public List<CmsDecorationDefintion> getDecorationDefinitions() {
285
286        return m_decorationDefinitions;
287    }
288
289    /**
290     * Gets the decoration bundle.<p>
291     *@return the decoration bundle to be used
292     */
293    public CmsDecorationBundle getDecorations() {
294
295        return m_decorations;
296    }
297
298    /**
299     * Returns the excludeattr.<p>
300     *
301     * @return the excludeattr
302     */
303    public List<String> getExcludeattr() {
304
305        return m_excludeattr;
306    }
307
308    /**
309     * Returns the excludes.<p>
310     *
311     * @return the excludes
312     */
313    public List<String> getExcludes() {
314
315        return m_excludes;
316    }
317
318    /**
319     * Returns the locale.<p>
320     *
321     * @return the locale
322     */
323    public Locale getLocale() {
324
325        return m_locale;
326    }
327
328    /**
329     * Returns the usedDecorations.<p>
330     *
331     * @return the usedDecorations
332     */
333    public List<String> getUsedDecorations() {
334
335        return m_usedDecorations;
336    }
337
338    /**
339     * Tests if a decoration key was used before in this configuration.<p>
340     * @param key the key to look for
341     * @return true if this key was already used
342     */
343    public boolean hasUsed(String key) {
344
345        return m_usedDecorations.contains(key);
346    }
347
348    /**
349     * @see org.opencms.jsp.decorator.I_CmsDecoratorConfiguration#init(org.opencms.file.CmsObject, java.lang.String, java.util.Locale)
350     */
351    public void init(CmsObject cms, String configFile, Locale locale) throws CmsException {
352
353        m_cms = cms;
354        m_locale = cms.getRequestContext().getLocale();
355        if (configFile != null) {
356            m_configFile = configFile;
357        }
358        if (locale != null) {
359            m_decorations = new CmsDecorationBundle(locale);
360            m_locale = locale;
361        }
362
363        if (m_configFile != null) {
364
365            // get the configuration file
366            CmsResource res = m_cms.readResource(m_configFile);
367            CmsFile file = m_cms.readFile(res);
368            CmsXmlContent configuration = CmsXmlContentFactory.unmarshal(m_cms, file);
369
370            // get the uselocale flag
371            // if this flag is not set to true, we must build locale independent decoration bundles
372            String uselocale = configuration.getValue(XPATH_USELOCALE, m_configurationLocale).getStringValue(m_cms);
373            if (!uselocale.equals("true")) {
374                m_locale = null;
375            }
376            // get the number of decoration definitions
377            int decorationDefCount = configuration.getIndexCount(XPATH_DECORATION, m_configurationLocale);
378            // get all the decoration definitions
379            for (int i = 1; i <= decorationDefCount; i++) {
380                CmsDecorationDefintion decDef = getDecorationDefinition(configuration, i);
381                m_decorationDefinitions.add(decDef);
382                CmsDecorationBundle decBundle = decDef.createDecorationBundle(m_cms, m_locale);
383                // merge it to the already existing decorations
384                m_decorations.putAll(decBundle.getAll());
385            }
386
387            // now read the exclude values
388            int excludeValuesCount = configuration.getIndexCount(XPATH_EXCLUDE, m_configurationLocale);
389            // get all the exclude definitions
390            for (int i = 1; i <= excludeValuesCount; i++) {
391                String excludeValue = configuration.getStringValue(
392                    m_cms,
393                    XPATH_EXCLUDE + "[" + i + "]",
394                    m_configurationLocale);
395                m_excludes.add(excludeValue.toLowerCase());
396            }
397
398            // now read the exclude attributes
399            int excludeAttrValuesCount = configuration.getIndexCount(XPATH_EXCLUDEATTR, m_configurationLocale);
400            // get all the exclude attribute definitions
401            for (int i = 1; i <= excludeAttrValuesCount; i++) {
402                String excludeAttrValue = configuration.getStringValue(
403                    m_cms,
404                    XPATH_EXCLUDEATTR + "[" + i + "]",
405                    m_configurationLocale);
406                m_excludeattr.add(excludeAttrValue.toLowerCase());
407            }
408
409        }
410    }
411
412    /**
413     * Tests if a tag is contained in the exclude list of the decorator.<p>
414     *
415     * @param tag the tag to test
416     * @return true if the tag is in the exclode list, false othwerwise.
417     */
418    public boolean isExcluded(String tag) {
419
420        return m_excludes.contains(tag.toLowerCase());
421    }
422
423    /**
424     * 
425     * @see org.opencms.jsp.decorator.I_CmsDecoratorConfiguration#isExcludedAttr(org.htmlparser.Tag)
426     */
427    public boolean isExcludedAttr(Tag tag) {
428
429        boolean isExcluded = false;
430        for (String attr : m_excludeattr) {
431            if (tag.getAttribute(attr.toLowerCase()) != null) {
432                isExcluded = true;
433                break;
434            }
435        }
436        return isExcluded;
437    }
438
439    /**
440     * Mark a decoration key as already used.<p>
441     * @param key the key to mark
442     */
443    public void markAsUsed(String key) {
444
445        m_usedDecorations.add(key);
446    }
447
448    /**
449     * Resets the used decoration keys.<p>
450     */
451    public void resetMarkedDecorations() {
452
453        m_usedDecorations = new ArrayList<String>();
454    }
455
456    /**
457     * Sets the cms.<p>
458     *
459     * @param cms the cms to set
460     */
461    public void setCms(CmsObject cms) {
462
463        m_cms = cms;
464    }
465
466    /**
467     * Sets the configFile.<p>
468     *
469     * @param configFile the configFile to set
470     */
471    public void setConfigFile(String configFile) {
472
473        m_configFile = configFile;
474    }
475
476    /**
477     * Sets the configurationLocale.<p>
478     *
479     * @param configurationLocale the configurationLocale to set
480     */
481    public void setConfigurationLocale(Locale configurationLocale) {
482
483        m_configurationLocale = configurationLocale;
484    }
485
486    /**
487     * Sets the decorationDefinitions.<p>
488     *
489     * @param decorationDefinitions the decorationDefinitions to set
490     */
491    public void setDecorationDefinitions(List<CmsDecorationDefintion> decorationDefinitions) {
492
493        m_decorationDefinitions = decorationDefinitions;
494    }
495
496    /**
497     * Sets the decoration bundle, overwriting an exiting one.<p>
498     *
499     * @param decorations new decoration bundle
500     */
501    public void setDecorations(CmsDecorationBundle decorations) {
502
503        m_decorations = decorations;
504    }
505
506    /**
507     * Sets the excludeattr.<p>
508     *
509     * @param excludeattr the excludeattr to set
510     */
511    public void setExcludeattr(List<String> excludeattr) {
512
513        m_excludeattr = excludeattr;
514    }
515
516    /**
517     * Sets the excludes.<p>
518     *
519     * @param excludes the excludes to set
520     */
521    public void setExcludes(List<String> excludes) {
522
523        m_excludes = excludes;
524    }
525
526    /**
527     * Sets the locale.<p>
528     *
529     * @param locale the locale to set
530     */
531    public void setLocale(Locale locale) {
532
533        m_locale = locale;
534    }
535
536    /**
537     * Sets the usedDecorations.<p>
538     *
539     * @param usedDecorations the usedDecorations to set
540     */
541    public void setUsedDecorations(List<String> usedDecorations) {
542
543        m_usedDecorations = usedDecorations;
544    }
545
546    /**
547     * @see java.lang.Object#toString()
548     */
549    @Override
550    public String toString() {
551
552        StringBuffer buf = new StringBuffer();
553        buf.append(this.getClass().getName());
554        buf.append(" [configFile = '");
555        buf.append(m_configFile);
556        buf.append("', decorations = '");
557        buf.append(m_decorations);
558        buf.append("', locale = '");
559        buf.append(m_locale);
560        buf.append("']");
561        return buf.toString();
562    }
563
564}