001/*
002 *  Copyright 2014 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.web.clientsideelement.styles;
017
018import java.util.Collections;
019import java.util.Date;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.commons.lang3.StringUtils;
029import org.apache.excalibur.source.Source;
030import org.apache.excalibur.source.SourceResolver;
031
032import org.ametys.cms.clientsideelement.styles.StaticHTMLEditorContentStyle;
033import org.ametys.cms.clientsideelement.styles.Style;
034import org.ametys.cms.clientsideelement.styles.StyleCategory;
035import org.ametys.web.repository.site.Site;
036import org.ametys.web.repository.site.SiteManager;
037import org.ametys.web.skin.Skin;
038import org.ametys.web.skin.SkinConfigurationHelper;
039import org.ametys.web.skin.SkinsManager;
040
041/**
042 * Based on a configuration like the StaticHTMLEditorStyleExtension but the file is located inside the current skin directory (skin/conf/edition-styles.xml).
043 */
044public class SkinHTMLEditorContentStyle extends StaticHTMLEditorContentStyle
045{
046    /** The assocation skinId lastUpdateDate ; to know for a given skin when its conf file was read for the last time */
047    protected Map<String, Long> _lastUpdates = new HashMap<>();
048    /** The assocation skinId Style ; to know for a given skin its style */
049    protected Map<String, StyleCategory> _paraStyleCategories = new HashMap<>();
050    /** The assocation skinId Style ; to know for a given skin its style */
051    protected Map<String, StyleCategory> _tableStyleCategories = new HashMap<>();
052    /** The assocation skinId Style ; to know for a given skin its style */
053    protected Map<String, StyleCategory> _imageStyleCategories = new HashMap<>();
054    /** The assocation skinId Style ; to know for a given skin its style */
055    protected Map<String, StyleCategory> _linkStyleCategories = new HashMap<>();
056    /** The assocation skinId Style ; to know for a given skin its style */
057    protected Map<String, StyleCategory> _ulStyleCategories = new HashMap<>();
058    /** The assocation skinId Style ; to know for a given skin its style */
059    protected Map<String, StyleCategory> _olStyleCategories = new HashMap<>();
060    
061    /** The excalibur source resolver */
062    protected SourceResolver _sourceResolver;
063    /** The sites manager */
064    protected SiteManager _siteManager;
065    /** The skins manager */
066    protected SkinsManager _skinsManager;
067    /** The helper for inheritable skin configuration */
068    protected SkinConfigurationHelper _skinConfigurationHelper;
069    
070    @Override
071    public void service(ServiceManager manager) throws ServiceException
072    {
073        super.service(manager);
074        _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
075        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
076        _skinsManager = (SkinsManager) manager.lookup(SkinsManager.ROLE);
077        _skinConfigurationHelper = (SkinConfigurationHelper) manager.lookup(SkinConfigurationHelper.ROLE);
078    }
079    
080    @Override
081    public void configure(Configuration configuration) throws ConfigurationException
082    {
083        // Do nothing
084    }
085    
086    @Override
087    protected String _getImport(Configuration configuration, Map<String, Object> contextualParameters)
088    {
089        String siteId = (String) contextualParameters.get("siteName");
090        if (siteId == null)
091        {
092            getLogger().info("Cannot determine the current skin because cannot determine current site. Continue as if there is no HTML skin styles.");
093            return null;
094        }
095
096        Site site = _siteManager.getSite(siteId);
097        String skinId = site.getSkinId();
098
099        String boURL = "/skins/" + skinId + "/resources/";
100        
101        String uri = configuration.getValue(null);
102        return StringUtils.isBlank(uri) ? null : boURL + uri;
103    }
104
105    @Override
106    public StyleCategory getPara(String category, Map<String, Object> contextualParameters)
107    {
108        if (!"content".equals(category))
109        {
110            return null;
111        }
112        String currentSkin = _updateStyleCategories(contextualParameters);
113        return _paraStyleCategories.get(currentSkin);
114    }
115    @Override
116    public StyleCategory getImage(String category, Map<String, Object> contextualParameters)
117    {
118        if (!"content".equals(category))
119        {
120            return null;
121        }
122        String currentSkin = _updateStyleCategories(contextualParameters);
123        return _imageStyleCategories.get(currentSkin);
124    }
125    @Override
126    public StyleCategory getLink(String category, Map<String, Object> contextualParameters)
127    {
128        if (!"content".equals(category))
129        {
130            return null;
131        }
132        String currentSkin = _updateStyleCategories(contextualParameters);
133        return _linkStyleCategories.get(currentSkin);
134    }
135    @Override
136    public StyleCategory getOrderedList(String category, Map<String, Object> contextualParameters)
137    {
138        if (!"content".equals(category))
139        {
140            return null;
141        }
142        String currentSkin = _updateStyleCategories(contextualParameters);
143        return _olStyleCategories.get(currentSkin);
144    }
145    @Override
146    public StyleCategory getTable(String category, Map<String, Object> contextualParameters)
147    {
148        if (!"content".equals(category))
149        {
150            return null;
151        }
152        String currentSkin = _updateStyleCategories(contextualParameters);
153        return _tableStyleCategories.get(currentSkin);
154    }
155    @Override
156    public StyleCategory getUnorderedList(String category, Map<String, Object> contextualParameters)
157    {
158        if (!"content".equals(category))
159        {
160            return null;
161        }
162        String currentSkin = _updateStyleCategories(contextualParameters);
163        return _ulStyleCategories.get(currentSkin);
164    }
165    
166    /**
167     * Update if necessary the values associated with the current skin
168     * @param contextualParameters Contextuals parameters transmitted by the environment.
169     * @return The current skin 
170     */
171    protected String _updateStyleCategories(Map<String, Object> contextualParameters)
172    {
173        String siteId = (String) contextualParameters.get("siteName");
174        if (siteId == null)
175        {
176            getLogger().info("Cannot determine the current skin because cannot determine current site. Continue as if there is no HTML skin styles.");
177            return null;
178        }
179
180        Site site = _siteManager.getSite(siteId);
181        String skinId = site.getSkinId();
182
183        String url = "skin:" + skinId + "://conf/edition-styles.xml"; 
184        
185        Source configurationFile = null;
186        try
187        {
188            configurationFile = _sourceResolver.resolveURI(url);
189            if (configurationFile.exists())
190            {
191                Long lastUpdate = _lastUpdates.get(skinId);
192                
193                if (lastUpdate == null || lastUpdate < configurationFile.getLastModified())
194                {
195                    Skin skin = _skinsManager.getSkin(skinId);
196                    Configuration configuration = _skinConfigurationHelper.getInheritanceMergedConfiguration(skin, "conf/edition-styles.xml", this.getClass().getResourceAsStream("skin-htmleditor-style-merge.xsl"));
197                    
198                    StyleCategory paraStyleCategory = _configureStyleCategory(configuration.getChild("para"), "skin." + skinId, null, contextualParameters);
199                    StyleCategory imageStyleCategory = _configureStyleCategory(configuration.getChild("image"), "skin." + skinId, IMAGE_DEFAULT_ICONS, contextualParameters);
200                    StyleCategory tableStyleCategory = _configureStyleCategory(configuration.getChild("table"), "skin." + skinId, TABLE_DEFAULT_ICONS, contextualParameters);
201                    StyleCategory linkStyleCategory = _configureStyleCategory(configuration.getChild("link"), "skin." + skinId, LINK_DEFAULT_ICONS, contextualParameters);
202                    StyleCategory ulStyleCategory = _configureStyleCategory(configuration.getChild("unorderedlist"), "skin." + skinId, UL_DEFAULT_ICONS, contextualParameters);
203                    StyleCategory olStyleCategory = _configureStyleCategory(configuration.getChild("orderedlist"), "skin." + skinId, OL_DEFAULT_ICONS, contextualParameters);
204                    
205                    _paraStyleCategories.put(skinId, paraStyleCategory);
206                    _imageStyleCategories.put(skinId, imageStyleCategory);
207                    _tableStyleCategories.put(skinId, tableStyleCategory);
208                    _linkStyleCategories.put(skinId, linkStyleCategory);
209                    _ulStyleCategories.put(skinId, ulStyleCategory);
210                    _olStyleCategories.put(skinId, olStyleCategory);
211                    
212                    _lastUpdates.put(skinId, configurationFile.getLastModified());
213                }
214            }
215            else
216            {
217                _defaultValues(skinId);
218            }
219        }
220        catch (Exception e)
221        {
222            _defaultValues(skinId);
223            if (getLogger().isWarnEnabled())
224            {
225                getLogger().warn("Cannot read the configuration file " + url + ". Continue as if file was not existing", e);
226            }
227        }
228        
229        return skinId;
230    }
231    
232    /**
233     * Set default values for the given skin
234     * @param skinId The skin
235     */
236    protected void _defaultValues(String skinId)
237    {
238        List<Style> emptyList = Collections.emptyList();
239        _paraStyleCategories.put(skinId, new StyleCategory(Collections.EMPTY_SET, Collections.EMPTY_SET, emptyList));
240        _lastUpdates.put(skinId, new Date().getTime());
241    }
242}