001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.clientsideelement.styles;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.LinkedHashSet;
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024
025import org.apache.avalon.framework.configuration.Configurable;
026import org.apache.avalon.framework.configuration.Configuration;
027import org.apache.avalon.framework.configuration.ConfigurationException;
028import org.apache.avalon.framework.logger.AbstractLogEnabled;
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.avalon.framework.service.ServiceManager;
031import org.apache.avalon.framework.service.Serviceable;
032import org.apache.commons.lang3.StringUtils;
033import org.apache.excalibur.source.SourceResolver;
034
035import org.ametys.runtime.i18n.I18nizableText;
036import org.ametys.runtime.plugin.component.PluginAware;
037
038/**
039 * This implementation is based upon a static configuration.
040 */
041public class StaticHTMLEditorStyleExtension extends AbstractLogEnabled implements HTMLEditorStyleExtensionPoint, Configurable, Serviceable, PluginAware
042{
043    /** Default icons style for table */
044    protected static final String[] TABLE_DEFAULT_ICONS = new String[] {"/plugins/cms/resources/img/content/edition/table/Table_Border_16.png", "/plugins/cms/resources/img/content/edition/table/Table_Border_32.png", "/plugins/cms/resources/img/content/edition/table/Table_Border_32.png"};
045    /** Default icons style for link */
046    protected static final String[] LINK_DEFAULT_ICONS = new String[] {"/plugins/cms/resources/img/content/edition/link/Style_Normal_16.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png"};
047    /** Default icons style for image */
048    protected static final String[] IMAGE_DEFAULT_ICONS = new String[] {"/plugins/cms/resources/img/content/edition/image/Image_Style_Border_16.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png"};
049    /** Default icons style for unordered list */
050    protected static final String[] UL_DEFAULT_ICONS = new String[] {"/plugins/cms/resources/img/content/edition/list/disc_16.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png"};
051    /** Default icons style for ordered list */
052    protected static final String[] OL_DEFAULT_ICONS = new String[] {"/plugins/cms/resources/img/content/edition/list/decimal_16.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png", "/plugins/cms/resources/img/content/edition/link/Style_Normal_32.png"};
053    
054    /** Excalibur source resolver */
055    protected SourceResolver _resolver;
056    /** The values of the file */
057    protected StyleCategory _paraStyleCategory;
058    /** The values of the file */
059    protected StyleCategory _tableStyleCategory;
060    /** The values of the file */
061    protected StyleCategory _linkStyleCategory;
062    /** The values of the file */
063    protected StyleCategory _imageStyleCategory;
064    /** The values of the file */
065    protected StyleCategory _ulStyleCategory;
066    /** The values of the file */
067    protected StyleCategory _olStyleCategory;
068    /** The plugin that declared the instance */
069    protected String _pluginName;
070    /** The feature that declared the instance */
071    protected String _featureName;
072    
073    @Override
074    public void service(ServiceManager manager) throws ServiceException
075    {
076        _resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
077    }
078    
079    @Override
080    public void setPluginInfo(String pluginName, String featureName, String id)
081    {
082        _pluginName = pluginName;
083        _featureName = featureName;
084    }
085    
086    @Override
087    public void configure(Configuration configuration) throws ConfigurationException
088    {
089        _configure(configuration, "plugin." + _pluginName, new HashMap<String, Object>());
090    }
091    
092    /**
093     * Configure this instance upon a configuration
094     * @param configuration The configuration
095     * @param defaultCatalogue The default i18n catalogue to use
096     * @param contextParameters Contextuals parameters transmitted by the environment.
097     * @throws ConfigurationException If the configuration is incorrect
098     */
099    protected void _configure(Configuration configuration, String defaultCatalogue, Map<String, Object> contextParameters) throws ConfigurationException
100    {
101        _paraStyleCategory = _configureStyleCategory(configuration.getChild("para"), defaultCatalogue, null, contextParameters);
102        _tableStyleCategory = _configureStyleCategory(configuration.getChild("table"), defaultCatalogue, TABLE_DEFAULT_ICONS, contextParameters);
103        _linkStyleCategory = _configureStyleCategory(configuration.getChild("link"), defaultCatalogue, LINK_DEFAULT_ICONS, contextParameters);
104        _imageStyleCategory = _configureStyleCategory(configuration.getChild("image"), defaultCatalogue, IMAGE_DEFAULT_ICONS, contextParameters);
105        _ulStyleCategory = _configureStyleCategory(configuration.getChild("unorderedlist"), defaultCatalogue, UL_DEFAULT_ICONS, contextParameters);
106        _olStyleCategory = _configureStyleCategory(configuration.getChild("orderedlist"), defaultCatalogue, OL_DEFAULT_ICONS, contextParameters);
107    }
108    
109    /**
110     * Configure this instance upon the style part of a configuration
111     * @param styleConfiguration The style part of the configuration
112     * @param defaultCatalogue The default i18n catalogue to use
113     * @param defaultIcons the path to the button's default icons in small, medium and large size
114     * @param contextParameters Contextuals parameters transmitted by the environment.
115     * @return The style that represents the values read
116     * @throws ConfigurationException If the configuration is incorrect
117     */
118    protected StyleCategory _configureStyleCategory(Configuration styleConfiguration, String defaultCatalogue, String[] defaultIcons, Map<String, Object> contextParameters) throws ConfigurationException
119    {
120        Set<String> boCSSFiles = new LinkedHashSet<>();
121        Set<String> inlineEditorCSSFiles = new LinkedHashSet<>();
122        
123        for (Configuration configuration : styleConfiguration.getChild("import").getChildren("button"))
124        {
125            boCSSFiles.add(_getImport(configuration, contextParameters));
126            // adding null will be ignored later
127        }
128        for (Configuration configuration : styleConfiguration.getChild("import").getChildren("inline-editor"))
129        {
130            inlineEditorCSSFiles.add(_getImport(configuration, contextParameters));
131            // adding null will be ignored later
132        }
133        
134        List<Style> styleList = new ArrayList<>();
135        for (Configuration styleConf : styleConfiguration.getChildren("style"))
136        {
137            Style style = _configureStyle(styleConf, defaultCatalogue, defaultIcons, contextParameters);
138            styleList.add(style);
139        }
140        
141        return new StyleCategory(boCSSFiles, inlineEditorCSSFiles, styleList);
142    }
143    
144    /**
145     * Determine an url from a configuration node.
146     * @param configuration Read the optional plugin attribute and concatenate it to the value of the node. Can be null
147     * @param contextParameters Contextuals parameters transmitted by the environment.
148     * @return The non-null path to the plugin resource
149     */
150    protected String _getImport(Configuration configuration, Map<String, Object> contextParameters)
151    {
152        String boPlugin = configuration.getAttribute("plugin", _pluginName);
153        String boFileLocation = "/plugins/" + boPlugin + "/resources/";
154        
155        String uri = configuration.getValue(null);
156        return StringUtils.isBlank(uri) ? null : boFileLocation + uri;
157    }
158    
159    /**
160     * Configure a style
161     * @param configuration The style configuration
162     * @param defaultCatalogue The default i18n catalogue to use
163     * @param defaultIcons the path to the button's default icons in small, medium and large size
164     * @param contextParameters Contextual parameters transmitted by the environment.
165     * @return The style configured
166     * @throws ConfigurationException If the configuration is incorrect
167     */
168    protected Style _configureStyle(Configuration configuration, String defaultCatalogue, String[] defaultIcons, Map<String, Object> contextParameters) throws ConfigurationException
169    {
170        String buttonSmallIcon = defaultIcons != null ? defaultIcons[0] : null;
171        String buttonMediumIcon = defaultIcons != null ? defaultIcons[1] : null;
172        String buttonLargeIcon = defaultIcons != null ? defaultIcons[2] : null;
173        I18nizableText buttonLabel;
174        I18nizableText buttonDescription;
175        String buttonCSSClass;
176
177        Configuration iconSmallConf = configuration.getChild("button").getChild("icon-small", false);
178        if (iconSmallConf != null)
179        {
180            buttonSmallIcon = _getImport(iconSmallConf, contextParameters);
181        }
182        
183        Configuration iconMediumConf = configuration.getChild("button").getChild("icon-medium", false);
184        if (iconMediumConf == null)
185        {
186            // Try to look for "icon" if no "icon-medium".
187            iconMediumConf = configuration.getChild("button").getChild("icon", false);
188        }
189        
190        if (iconMediumConf != null)
191        {
192            buttonMediumIcon = _getImport(iconMediumConf, contextParameters);
193        }
194        
195        Configuration iconLargeConf = configuration.getChild("button").getChild("icon-large", false);
196        if (iconLargeConf == null)
197        {
198            // Try to look for "icon" if no "icon-large".
199            iconLargeConf = configuration.getChild("button").getChild("icon", false);
200        }
201        
202        if (iconLargeConf != null)
203        {
204            buttonLargeIcon = _getImport(iconLargeConf, contextParameters);
205        }
206        
207        Configuration labelConf = configuration.getChild("button").getChild("label");
208        if (labelConf.getAttributeAsBoolean("i18n", false))
209        {
210            buttonLabel = new I18nizableText(defaultCatalogue, labelConf.getValue());
211        }
212        else 
213        {
214            buttonLabel = new I18nizableText(labelConf.getValue());
215        }
216
217        Configuration descriptionConf = configuration.getChild("button").getChild("description");
218        if (descriptionConf.getAttributeAsBoolean("i18n", false))
219        {
220            buttonDescription = new I18nizableText(defaultCatalogue, descriptionConf.getValue());
221        }
222        else 
223        {
224            buttonDescription = new I18nizableText(descriptionConf.getValue());
225        }
226        
227        buttonCSSClass = configuration.getChild("button").getChild("cssclass").getValue("");
228        
229        String inlineEditorRender = configuration.getChild("inline-editor").getValue();
230        
231        return new Style(buttonLabel, buttonDescription, buttonSmallIcon, buttonMediumIcon, buttonLargeIcon, buttonCSSClass, inlineEditorRender);
232    }
233
234    @Override
235    public StyleCategory getPara(Map<String, Object> contextualParameters)
236    {
237        return _paraStyleCategory;
238    }
239    
240    @Override
241    public StyleCategory getTable(Map<String, Object> contextualParameters)
242    {
243        return _tableStyleCategory;
244    }
245    
246    @Override
247    public StyleCategory getLink(Map<String, Object> contextualParameters)
248    {
249        return _linkStyleCategory;
250    }
251    
252    @Override
253    public StyleCategory getImage(Map<String, Object> contextualParameters)
254    {
255        return _imageStyleCategory;
256    }
257    
258    @Override
259    public StyleCategory getUnorderedList(Map<String, Object> contextualParameters)
260    {
261        return _ulStyleCategory;
262    }
263    
264    @Override
265    public StyleCategory getOrderedList(Map<String, Object> contextualParameters)
266    {
267        return _olStyleCategory;
268    }
269}