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.web.clientsideelement;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.HashSet;
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024
025import org.apache.avalon.framework.configuration.Configuration;
026import org.apache.avalon.framework.configuration.ConfigurationException;
027import org.apache.avalon.framework.configuration.DefaultConfiguration;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.slf4j.LoggerFactory;
031
032import org.ametys.core.ui.Callable;
033import org.ametys.core.ui.StaticClientSideElement;
034import org.ametys.core.util.I18nUtils;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.runtime.i18n.I18nizableText;
037import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
038import org.ametys.web.repository.page.ModifiablePage;
039import org.ametys.web.repository.page.Page;
040import org.ametys.web.repository.page.Page.PageType;
041import org.ametys.web.repository.site.SiteManager;
042import org.ametys.web.skin.Skin;
043import org.ametys.web.skin.SkinTemplate;
044import org.ametys.web.skin.SkinsManager;
045import org.ametys.web.skin.TemplatesAssignmentHandler;
046
047/**
048 * This element finally creates a gallery button with one item per template  
049 */
050public class TemplatesMenu extends AbstractPageMenu
051{
052    /** The plugin in which are the templates resources (messages and icons). */
053    protected static final String _RESOURCES_PLUGIN = "web";
054    
055    /** The skins manager */
056    protected SkinsManager _skinsManager;
057    /** The template assignment handler */
058    protected TemplatesAssignmentHandler _templatesAssignmentHandler;
059    /** The site manager */
060    protected SiteManager _siteManager;
061    /** The i18n utils */
062    protected I18nUtils _i18nUtils;
063    
064    @Override
065    public void service(ServiceManager smanager) throws ServiceException
066    {
067        super.service(smanager);
068        
069        _skinsManager = (SkinsManager) smanager.lookup(SkinsManager.ROLE);
070        _templatesAssignmentHandler = (TemplatesAssignmentHandler) smanager.lookup(TemplatesAssignmentHandler.ROLE);
071        _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE);
072        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
073        _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE);
074    }
075    
076    /**
077     * Get the available templates for pages
078     * @param pageIds The ids of pages
079     * @return the list of templates' name
080     */
081    @Callable
082    public Map<String, Object> getStatus (List<String> pageIds)
083    {
084        Map<String, Object> result = new HashMap<>();
085        
086        result.put("nomodifiable-pages", new ArrayList<Map<String, Object>>());
087        result.put("noright-pages", new ArrayList<Map<String, Object>>());
088        result.put("allright-pages", new ArrayList<Map<String, Object>>());
089        
090        Set<String> availableTemplateIds = new HashSet<>();
091        for (String pageId : pageIds)
092        {
093            Page page = _resolver.resolveById(pageId);
094            availableTemplateIds.addAll(_templatesAssignmentHandler.getAvailablesTemplates(page));
095            
096            if (!(page instanceof ModifiablePage))
097            {
098                Map<String, Object> pageParams = getPageDefaultParameters(page);
099                pageParams.put("description", getNoModifiablePageDescription(page));
100
101                @SuppressWarnings("unchecked")
102                List<Map<String, Object>> norightPages = (List<Map<String, Object>>) result.get("nomodifiable-pages");
103                norightPages.add(pageParams);
104            }
105            else if (!hasRight(page))
106            {
107                Map<String, Object> pageParams = getPageDefaultParameters(page);
108                pageParams.put("description", getNoRightPageDescription(page));
109
110                @SuppressWarnings("unchecked")
111                List<Map<String, Object>> norightPages = (List<Map<String, Object>>) result.get("noright-pages");
112                norightPages.add(pageParams);
113            }
114            else
115            {
116                Map<String, Object> pageParams = getPageDefaultParameters(page);
117                pageParams.put("description", getAllRightPageDescription(page));
118                if (page.getType() == PageType.CONTAINER)
119                {
120                    pageParams.put("template", page.getTemplate());
121                }
122                
123                @SuppressWarnings("unchecked")
124                List<Map<String, Object>> allRightPages = (List<Map<String, Object>>) result.get("allright-pages");
125                allRightPages.add(pageParams);
126            }
127        }
128        
129        result.put("templates", new ArrayList<>(availableTemplateIds));
130        return result;
131    }
132    
133    @Override
134    public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters)
135    {
136        String siteName = (String) contextParameters.get("siteName");
137        
138        String skinId = _siteManager.getSite(siteName).getSkinId();
139        Skin skin = _skinsManager.getSkin(skinId);
140        
141        if (skin.getTemplates().size() == 0)
142        {
143            // Hide menu if there is no template
144            return new ArrayList<>();
145        }
146            
147        return super.getScripts(ignoreRights, contextParameters);
148    }
149    
150    
151    @Override
152    protected void _getGalleryItems(Map<String, Object> parameters, Map<String, Object> contextualParameters)
153    {
154        try
155        {
156            _lazyInitializeTemplateGallery(contextualParameters);
157        }
158        catch (Exception e)
159        {
160            throw new IllegalStateException("Unable to lookup client side element local components", e);
161        }
162        
163        super._getGalleryItems(parameters, contextualParameters);
164    }
165    
166    private void _lazyInitializeTemplateGallery(Map<String, Object> contextualParameters) throws ConfigurationException
167    {
168        // We need to dispose and use a new manager each time as items depends on the current site
169        // FIXME make a smart cache by skin ? The cache has to be clear when the skin is updated
170        _galleryItemManager.dispose();
171        
172        _galleryItemManager = new ThreadSafeComponentManager<>();
173        _galleryItemManager.setLogger(LoggerFactory.getLogger("cms.plugin.threadsafecomponent"));
174        _galleryItemManager.service(_smanager);
175        
176        String siteName = (String) contextualParameters.get("siteName");
177        
178        String skinId = _siteManager.getSite(siteName).getSkinId();
179        Set<String> availablesTemplates = _templatesAssignmentHandler.getAvailablesTemplates(skinId);
180        
181        Skin skin = _skinsManager.getSkin(skinId);
182        
183        if (availablesTemplates.size() > 0)
184        {
185            GalleryItem galleryItem = new GalleryItem();
186            
187            GalleryGroup galleryGroup = new GalleryGroup(new I18nizableText("plugin." + _RESOURCES_PLUGIN, "PLUGINS_WEB_PAGE_TEMPLATESMENU_GROUP_LABEL"));
188            galleryItem.addGroup(galleryGroup);
189                
190            for (String templateId : availablesTemplates)
191            {
192                String id = this.getId() + "." + templateId;
193                
194                SkinTemplate template = skin.getTemplate(templateId);
195                Configuration conf = _getTemplateItemConfiguration (id, template);
196                _galleryItemManager.addComponent(_pluginName, null, id, StaticClientSideElement.class, conf);
197                galleryGroup.addItem(new UnresolvedItem(id, true));
198            }
199            
200            _galleryItems.add(galleryItem);
201        }
202        
203        if (_galleryItems.size() > 0)
204        {
205            try
206            {
207                _galleryItemManager.initialize();
208            }
209            catch (Exception e)
210            {
211                throw new ConfigurationException("Unable to lookup parameter local components", e);
212            }
213        }
214    }
215    
216    /**
217     * Get the configuration for a language item
218     * @param itemId The item id
219     * @param template The template used for the item
220     * @return The configuration
221     */
222    protected Configuration _getTemplateItemConfiguration (String itemId, SkinTemplate template)
223    {
224        DefaultConfiguration conf = new DefaultConfiguration("extension");
225        conf.setAttribute("id", itemId);
226        
227        DefaultConfiguration classConf = new DefaultConfiguration("class");
228        classConf.setAttribute("name", "Ametys.ribbon.element.ui.ButtonController");
229        
230        // Label
231        DefaultConfiguration labelConf = new DefaultConfiguration("label");
232        labelConf.setValue(_i18nUtils.translate(template.getLabel()));
233        classConf.addChild(labelConf);
234        
235        // Description
236        DefaultConfiguration descConf = new DefaultConfiguration("description");
237        descConf.setValue(_i18nUtils.translate(template.getDescription()));
238        classConf.addChild(descConf);
239        
240        // Name
241        DefaultConfiguration nameConf = new DefaultConfiguration("name");
242        nameConf.setValue(template.getId());
243        classConf.addChild(nameConf);
244        
245        // Icons
246        DefaultConfiguration iconSmallConf = new DefaultConfiguration("icon-small");
247        iconSmallConf.setValue(template.getSmallImage());
248        classConf.addChild(iconSmallConf);
249        DefaultConfiguration iconMediumConf = new DefaultConfiguration("icon-medium");
250        iconMediumConf.setValue(template.getMediumImage());
251        classConf.addChild(iconMediumConf);
252        DefaultConfiguration iconLargeConf = new DefaultConfiguration("icon-large");
253        iconLargeConf.setValue(template.getLargeImage());
254        classConf.addChild(iconLargeConf);
255        
256        // Toggle button
257        DefaultConfiguration toggleEnabledConf = new DefaultConfiguration("toggle-enabled");
258        toggleEnabledConf.setValue("true");
259        classConf.addChild(toggleEnabledConf);
260        
261        // Common configuration
262        @SuppressWarnings("unchecked")
263        Map<String, Object> commonConfig = (Map<String, Object>) this._script.getParameters().get("items-config");
264        for (String tagName : commonConfig.keySet())
265        {
266            DefaultConfiguration c = new DefaultConfiguration(tagName);
267            c.setValue(String.valueOf(commonConfig.get(tagName)));
268            classConf.addChild(c);
269        }
270        
271        conf.addChild(classConf);
272        return conf;
273    }
274    
275}