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 StaticHTMLEditorStyle extends AbstractLogEnabled implements HTMLEditorStyle, 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, "param.edition-styles", 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", null);
153        
154        String boFileLocation;
155        if (StringUtils.isNotBlank(boPlugin))
156        {
157            boFileLocation = "/plugins/" + boPlugin + "/resources/";
158        }
159        else
160        {
161            boFileLocation = "/param_resources/edition-styles/";
162        }
163        
164        String uri = configuration.getValue(null);
165        return StringUtils.isBlank(uri) ? null : boFileLocation + uri;
166    }
167    
168    /**
169     * Configure a style
170     * @param configuration The style configuration
171     * @param defaultCatalogue The default i18n catalogue to use
172     * @param defaultIcons the path to the button's default icons in small, medium and large size
173     * @param contextParameters Contextual parameters transmitted by the environment.
174     * @return The style configured
175     * @throws ConfigurationException If the configuration is incorrect
176     */
177    protected Style _configureStyle(Configuration configuration, String defaultCatalogue, String[] defaultIcons, Map<String, Object> contextParameters) throws ConfigurationException
178    {
179        String buttonSmallIcon = defaultIcons != null ? defaultIcons[0] : null;
180        String buttonMediumIcon = defaultIcons != null ? defaultIcons[1] : null;
181        String buttonLargeIcon = defaultIcons != null ? defaultIcons[2] : null;
182        I18nizableText buttonLabel;
183        I18nizableText buttonDescription;
184        String buttonCSSClass;
185
186        Configuration iconSmallConf = configuration.getChild("button").getChild("icon-small", false);
187        if (iconSmallConf != null)
188        {
189            buttonSmallIcon = _getImport(iconSmallConf, contextParameters);
190        }
191        
192        Configuration iconMediumConf = configuration.getChild("button").getChild("icon-medium", false);
193        if (iconMediumConf == null)
194        {
195            // Try to look for "icon" if no "icon-medium".
196            iconMediumConf = configuration.getChild("button").getChild("icon", false);
197        }
198        
199        if (iconMediumConf != null)
200        {
201            buttonMediumIcon = _getImport(iconMediumConf, contextParameters);
202        }
203        
204        Configuration iconLargeConf = configuration.getChild("button").getChild("icon-large", false);
205        if (iconLargeConf == null)
206        {
207            // Try to look for "icon" if no "icon-large".
208            iconLargeConf = configuration.getChild("button").getChild("icon", false);
209        }
210        
211        if (iconLargeConf != null)
212        {
213            buttonLargeIcon = _getImport(iconLargeConf, contextParameters);
214        }
215        
216        Configuration labelConf = configuration.getChild("button").getChild("label");
217        if (labelConf.getAttributeAsBoolean("i18n", false))
218        {
219            buttonLabel = new I18nizableText(defaultCatalogue, labelConf.getValue());
220        }
221        else 
222        {
223            buttonLabel = new I18nizableText(labelConf.getValue());
224        }
225
226        Configuration descriptionConf = configuration.getChild("button").getChild("description");
227        if (descriptionConf.getAttributeAsBoolean("i18n", false))
228        {
229            buttonDescription = new I18nizableText(defaultCatalogue, descriptionConf.getValue());
230        }
231        else 
232        {
233            buttonDescription = new I18nizableText(descriptionConf.getValue());
234        }
235        
236        buttonCSSClass = configuration.getChild("button").getChild("cssclass").getValue("");
237        
238        String inlineEditorRender = configuration.getChild("inline-editor").getValue();
239        
240        return new Style(buttonLabel, buttonDescription, buttonSmallIcon, buttonMediumIcon, buttonLargeIcon, buttonCSSClass, inlineEditorRender);
241    }
242
243    @Override
244    public StyleCategory getPara(Map<String, Object> contextualParameters)
245    {
246        return _paraStyleCategory;
247    }
248    
249    @Override
250    public StyleCategory getTable(Map<String, Object> contextualParameters)
251    {
252        return _tableStyleCategory;
253    }
254    
255    @Override
256    public StyleCategory getLink(Map<String, Object> contextualParameters)
257    {
258        return _linkStyleCategory;
259    }
260    
261    @Override
262    public StyleCategory getImage(Map<String, Object> contextualParameters)
263    {
264        return _imageStyleCategory;
265    }
266    
267    @Override
268    public StyleCategory getUnorderedList(Map<String, Object> contextualParameters)
269    {
270        return _ulStyleCategory;
271    }
272    
273    @Override
274    public StyleCategory getOrderedList(Map<String, Object> contextualParameters)
275    {
276        return _olStyleCategory;
277    }
278}