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, 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.ade.configuration.plugins;
029
030import org.opencms.file.CmsObject;
031import org.opencms.main.CmsLog;
032import org.opencms.relations.CmsLink;
033import org.opencms.relations.CmsLinkInfo;
034import org.opencms.xml.content.I_CmsXmlContentLocation;
035import org.opencms.xml.content.I_CmsXmlContentValueLocation;
036import org.opencms.xml.types.CmsXmlVarLinkValue;
037
038import java.util.ArrayList;
039import java.util.Collections;
040import java.util.HashMap;
041import java.util.List;
042import java.util.Map;
043
044import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
045import org.apache.commons.lang3.builder.ToStringStyle;
046import org.apache.commons.logging.Log;
047
048/**
049 * Bean representing a template plugin.
050 *
051 * <p>Template plugins are links to external resources which are categorized into named groups and provided either by
052 * formatters of elements in the current page, or by the current sitemap configuration. They can be programmatically
053 * accessed by group name from the template. They also have an order attribute to control the order in which they wil be returned
054 * (plugins will be sorted by descending order).
055 */
056public class CmsTemplatePlugin {
057
058    /** Attribute node name. */
059    public static final String N_ATTRIBUTE = "Attribute";
060
061    /** Content value node name. */
062    public static final String N_GROUP = "Group";
063
064    /** Key node name. */
065    public static final String N_KEY = "Key";
066
067    /** Content value node name. */
068    public static final String N_ORDER = "Order";
069
070    /** XML node name. */
071    public static final String N_TARGET = "Target";
072
073    /** Value node name. */
074    public static final String N_VALUE = "Value";
075
076    /** Logger instance for this class. */
077    private static final Log LOG = CmsLog.getLog(CmsTemplatePlugin.class);
078
079    /** The map of attributes. */
080    private Map<String, String> m_attributes;
081
082    /** The plugin group. */
083    private String m_group;
084
085    /** The order of the plugin. */
086    private int m_order;
087
088    /** The origin of the plugin, for debugging purposes. */
089    private String m_origin;
090
091    /** The plugin target. */
092    private CmsLinkInfo m_target;
093
094    /**
095     * Creates a new instance.
096     *
097     * @param target the plugin target
098     * @param group the plugin group
099     * @param order the plugin order
100     * @param origin the origin from which the plugin was read (for debugging)
101     * @param attributes the attribute map
102     */
103    public CmsTemplatePlugin(
104        CmsLinkInfo target,
105        String group,
106        int order,
107        String origin,
108        Map<String, String> attributes) {
109
110        m_target = target;
111        m_group = group;
112        m_order = order;
113        m_origin = origin;
114        m_attributes = Collections.unmodifiableMap(attributes);
115    }
116
117    /**
118     * Parses the template plugins.
119     *
120     * @param cms the CMS context
121     * @param parent the parent location under which the template plugins are located
122     * @param subName the node name for the template plugins
123     *
124     * @return the list of parsed template plugins
125     */
126    public static List<CmsTemplatePlugin> parsePlugins(CmsObject cms, I_CmsXmlContentLocation parent, String subName) {
127
128        List<CmsTemplatePlugin> result = new ArrayList<>();
129        for (I_CmsXmlContentValueLocation pluginLoc : parent.getSubValues(subName)) {
130            try {
131                CmsTemplatePlugin plugin = parsePlugin(cms, pluginLoc);
132                if (plugin != null) {
133                    result.add(plugin);
134                }
135            } catch (Exception e) {
136                LOG.error(
137                    "Error reading plugin in "
138                        + parent.getDocument().getFile().getRootPath()
139                        + ": "
140                        + e.getLocalizedMessage(),
141                    e);
142            }
143        }
144        return result;
145    }
146
147    /**
148     * Parses a template plugin from the XML content.
149     *
150     * @param cms the CMS context
151     * @param pluginLocation the location representing the template plugin
152     *
153     * @return the parsed template plugin
154     */
155    private static CmsTemplatePlugin parsePlugin(CmsObject cms, I_CmsXmlContentValueLocation pluginLocation) {
156
157        String groupStr = pluginLocation.getSubValue(N_GROUP).getValue().getStringValue(cms).trim();
158        String origin = pluginLocation.getValue().getDocument().getFile().getRootPath();
159        I_CmsXmlContentValueLocation orderLoc = pluginLocation.getSubValue(N_ORDER);
160        int order = 0;
161        if (orderLoc != null) {
162            order = Integer.parseInt(orderLoc.getValue().getStringValue(cms).trim());
163        }
164        CmsXmlVarLinkValue target = (CmsXmlVarLinkValue)(pluginLocation.getSubValue(N_TARGET).getValue());
165        CmsLink link = target.getLink(cms);
166
167        Map<String, String> attributes = new HashMap<>();
168        for (I_CmsXmlContentValueLocation attrLoc : pluginLocation.getSubValues(N_ATTRIBUTE)) {
169            String key = attrLoc.getSubValue(N_KEY).getValue().getStringValue(cms);
170            String value = attrLoc.getSubValue(N_VALUE).getValue().getStringValue(cms);
171            attributes.put(key, value);
172        }
173        CmsTemplatePlugin plugin = new CmsTemplatePlugin(
174            link != null ? link.toLinkInfo() : CmsLinkInfo.EMPTY,
175            groupStr,
176            order,
177            origin,
178            Collections.unmodifiableMap(attributes));
179        return plugin;
180    }
181
182    /**
183     * Gets the configured attributes of the plugin.
184     *
185     * @return the plugin attributes
186     */
187    public Map<String, String> getAttributes() {
188
189        return Collections.unmodifiableMap(m_attributes);
190    }
191
192    /**
193     * Gets the plugin group.
194     *
195     * @return the plugin group
196     */
197    public String getGroup() {
198
199        return m_group;
200    }
201
202    /**
203     * Returns the plugin order.
204     *
205     * <p>Plugins are sorted by descending order when retrieved in the template.
206     *
207     * @return the plugin order
208     */
209    public int getOrder() {
210
211        return m_order;
212    }
213
214    /**
215     * The plugin origin, for debugging purposes.
216     *
217     * @return the plugin origin
218     */
219    public String getOrigin() {
220
221        return m_origin;
222    }
223
224    /**
225     * Gets the plugin target.
226     *
227     * <p>When the plugins for a given group are retrieved, duplicate targets will be removed, and the position
228     * of each target in the resulting list is decided by the highest order for that target.
229     *
230     * @return the target
231     */
232    public CmsLinkInfo getTarget() {
233
234        return m_target;
235    }
236
237    /**
238     * @see java.lang.Object#toString()
239     */
240    @Override
241    public String toString() {
242
243        return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
244
245    }
246}