001/*
002 *  Copyright 2013 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.skinfactory.clientsidelement;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.LinkedHashMap;
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.apache.cocoon.ProcessingException;
031
032import org.ametys.core.ui.ClientSideElement;
033import org.ametys.core.ui.SimpleMenu;
034import org.ametys.core.ui.StaticClientSideElement;
035import org.ametys.core.util.I18nUtils;
036import org.ametys.runtime.i18n.I18nizableText;
037import org.ametys.skinfactory.model.ModelDesignsManager;
038import org.ametys.skinfactory.model.ModelDesignsManager.Design;
039import org.ametys.web.skin.SkinModelsManager;
040
041/**
042 * {@link StaticClientSideElement} for design of model
043 *
044 */
045public class DesignsMenu extends SimpleMenu
046{
047    private ModelDesignsManager _designsManager;
048    private boolean _designsInitialized;
049    private SkinModelsManager _modelsManager;
050    private I18nUtils _i18nUtils;
051    
052    @Override
053    public void service(ServiceManager smanager) throws ServiceException
054    {
055        super.service(smanager);
056        _designsManager = (ModelDesignsManager) smanager.lookup(ModelDesignsManager.ROLE);
057        _modelsManager = (SkinModelsManager) smanager.lookup(SkinModelsManager.ROLE);
058        _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE);
059    }
060
061    @Override
062    public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters)
063    {
064        Set<String> models = _modelsManager.getModels();
065        if (models != null)
066        {
067            // Test to find if at lease one model has a design (if not, no scripts are added)
068            boolean hasDesigns = models.stream()
069                    .map(_designsManager::getDesigns)
070                    .anyMatch(d -> !d.isEmpty());
071            
072            if (hasDesigns)
073            {
074                return super.getScripts(ignoreRights, contextParameters);
075            }
076        }
077        
078        return Collections.EMPTY_LIST;
079    }
080    
081    @Override
082    protected void _getGalleryItems(Map<String, Object> parameters, Map<String, Object> contextualParameters)
083    {
084        try
085        {
086            _lazyInitializeDesignsGallery();
087        }
088        catch (Exception e)
089        {
090            throw new IllegalStateException("Unable to lookup client side element local components", e);
091        }
092        
093        if (_galleryItems.size() > 0)
094        {
095            parameters.put("gallery-item", new LinkedHashMap<String, Object>());
096            
097            for (GalleryItem galleryItem : _galleryItems)
098            {
099                @SuppressWarnings("unchecked")
100                Map<String, Object> galleryItems = (Map<String, Object>) parameters.get("gallery-item");
101                galleryItems.put("gallery-groups", new ArrayList<>());
102                
103                for (GalleryGroup galleryGp : galleryItem.getGroups())
104                {
105                    @SuppressWarnings("unchecked")
106                    List<Object> galleryGroups = (List<Object>) galleryItems.get("gallery-groups");
107                    
108                    Map<String, Object> groupParams = new LinkedHashMap<>();
109                    
110                    I18nizableText label = galleryGp.getLabel();
111                    groupParams.put("label", label);
112                    
113                    // Group items
114                    List<String> gpItems = new ArrayList<>();
115                    for (ClientSideElement element : galleryGp.getItems())
116                    {
117                        gpItems.add(element.getId());
118                    }
119                    
120                    if (gpItems.size() > 0)
121                    {
122                        groupParams.put("items", gpItems);
123                        galleryGroups.add(groupParams);
124                    }
125                }
126            }
127        }
128    }
129    
130
131    /**
132     * Lazy initialization of the design gallery
133     * @throws ConfigurationException if the design configuration is wrong
134     * @throws ProcessingException if an error occurs when retrieving the models
135     */
136    private synchronized void _lazyInitializeDesignsGallery() throws ConfigurationException, ProcessingException
137    {
138        if (!_designsInitialized)
139        {
140            Set<String> models = _modelsManager.getModels();
141            
142            GalleryItem galleryItem = new GalleryItem();
143            
144            GalleryGroup galleryGroup = new GalleryGroup(new I18nizableText("plugin." + _pluginName, "PLUGINS_SKINFACTORY_DESIGNMENU_GROUP_LABEL"));
145            galleryItem.addGroup(galleryGroup);
146
147            for (String modelName : models)
148            {
149                Map<String, Design> designs = _designsManager.getDesigns(modelName);
150            
151                if (designs.size() > 0)
152                {
153                    for (Design design : designs.values())
154                    {
155                        String itemId = this.getId() + "-" + modelName + "-" + design.getId();
156                        
157                        Configuration conf = _getDesignConfiguration(itemId, design, modelName);
158                        _getGalleryItemManager().addComponent(_pluginName, null, itemId, StaticClientSideElement.class, conf);
159                        galleryGroup.addItem(new UnresolvedItem(itemId, true));
160                    }
161                }
162            }
163            
164            _galleryItems.add(galleryItem);
165            
166            try
167            {
168                _getGalleryItemManager().initialize();
169            }
170            catch (Exception e)
171            {
172                throw new ConfigurationException("Unable to lookup parameter local components", e);
173            }
174            
175            _designsInitialized = true;
176        }
177    }
178
179    /**
180     * Get the configuration of the model item
181     * @param id The id of item
182     * @param design The design
183     * @param modelName The model name
184     * @return The configuration
185     */
186    protected Configuration _getDesignConfiguration(String id, Design design, String modelName)
187    {
188        DefaultConfiguration conf = new DefaultConfiguration("extension");
189        conf.setAttribute("id", id);
190        
191        DefaultConfiguration classConf = new DefaultConfiguration("class");
192        classConf.setAttribute("name", "Ametys.ribbon.element.ui.ButtonController");
193        
194        // Label
195        DefaultConfiguration labelConf = new DefaultConfiguration("label");
196        labelConf.setValue(_i18nUtils.translate(design.getLabel()));
197        classConf.addChild(labelConf);
198        
199        // Description
200        DefaultConfiguration descriptionConf = new DefaultConfiguration("description");
201        descriptionConf.setValue(_i18nUtils.translate(design.getDescription()));
202        classConf.addChild(descriptionConf);
203        
204        // Icons
205        DefaultConfiguration iconSmallConf = new DefaultConfiguration("icon-small");
206        iconSmallConf.setValue(design.getIcon());
207        classConf.addChild(iconSmallConf);
208        DefaultConfiguration iconMediumConf = new DefaultConfiguration("icon-medium");
209        iconMediumConf.setValue(design.getIcon());
210        classConf.addChild(iconMediumConf);
211        DefaultConfiguration iconLargeConf = new DefaultConfiguration("icon-large");
212        iconLargeConf.setValue(design.getIcon());
213        classConf.addChild(iconLargeConf);
214
215        // Model name
216        DefaultConfiguration modelNameConf = new DefaultConfiguration("modelName");
217        modelNameConf.setValue(modelName);
218        classConf.addChild(modelNameConf);
219        
220        // Design id
221        DefaultConfiguration designConf = new DefaultConfiguration("designId");
222        designConf.setValue(design.getId());
223        classConf.addChild(designConf);
224        
225        // Common configuration
226        @SuppressWarnings("unchecked")
227        Map<String, Object> commonConfig = (Map<String, Object>) this._script.getParameters().get("items-config");
228        for (String tagName : commonConfig.keySet())
229        {
230            DefaultConfiguration c = new DefaultConfiguration(tagName);
231            c.setValue(String.valueOf(commonConfig.get(tagName)));
232            classConf.addChild(c);
233        }
234        
235        conf.addChild(classConf);
236        return conf;
237    }
238}