001/*
002 *  Copyright 2016 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.runtime.model.checker;
017
018import java.util.HashMap;
019import java.util.LinkedHashSet;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.component.ComponentException;
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.ConfigurationException;
026import org.apache.commons.lang3.StringUtils;
027
028import org.ametys.runtime.i18n.I18nizableText;
029import org.ametys.runtime.model.ItemParserHelper;
030import org.ametys.runtime.model.ItemParserHelper.ConfigurationAndPluginName;
031import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
032
033/**
034 * Parameter checker parser from an XML configuration. 
035 */
036public class ItemCheckerParser
037{
038    /** The parameter checker component manager. */
039    protected ThreadSafeComponentManager<ItemChecker> _parameterCheckerManager;
040    
041    /** The name of the plugin declaring this parameter checker */
042    protected String _pluginName;
043    
044    private final Map<ItemCheckerDescriptor, String> _parameterCheckersToLookup = new HashMap<>();
045    
046    /**
047     * Create a parameter checker parser
048     * @param paramCheckerManager the parameter checker.
049     */
050    public ItemCheckerParser(ThreadSafeComponentManager<ItemChecker> paramCheckerManager)
051    {
052        _parameterCheckerManager = paramCheckerManager;
053    }
054    
055    /**
056     * Parse a parameter checker from a XML configuration.
057     * @param pluginName the plugin's name declaring this parameter.
058     * @param paramCheckerConfig the XML configuration.
059     * @return the {@link ItemCheckerDescriptor} for the parsed parameter checker
060     * @throws ConfigurationException if the configuration is not valid.
061     */
062    public ItemCheckerDescriptor parseParameterChecker(String pluginName, Configuration paramCheckerConfig) throws ConfigurationException
063    {
064        ItemCheckerDescriptor parameterChecker = _getParameterCheckerDescriptorInstance();
065         
066        String parameterId = paramCheckerConfig.getAttribute("id");
067        String concreteClass = paramCheckerConfig.getAttribute("class");
068
069        Configuration smallIconConfig = paramCheckerConfig.getChild("icon-small");
070        String smallIconPath = smallIconConfig.getValue("");
071        if (StringUtils.isNotEmpty(smallIconPath))
072        {
073            String plugin = smallIconConfig.getAttribute("plugin", pluginName);
074            smallIconPath = "/plugins/" + plugin + "/resources/" + smallIconPath;
075        }
076        
077        Configuration mediumIconConfig = paramCheckerConfig.getChild("icon-medium");
078        String mediumIconPath = mediumIconConfig.getValue("");
079        if (StringUtils.isNotEmpty(mediumIconPath))
080        {
081            String plugin = mediumIconConfig.getAttribute("plugin", pluginName);
082            mediumIconPath = "/plugins/" + plugin + "/resources/" + mediumIconPath;
083        }
084        
085        Configuration largeIconConfig = paramCheckerConfig.getChild("icon-large");
086        String largeIconPath = largeIconConfig.getValue("");
087        if (StringUtils.isNotEmpty(largeIconPath))
088        {
089            String plugin = largeIconConfig.getAttribute("plugin", pluginName);
090            largeIconPath = "/plugins/" + plugin + "/resources/" + largeIconPath;
091        }
092        
093        ConfigurationAndPluginName checkerConfigAndPluginName = new ConfigurationAndPluginName(paramCheckerConfig, pluginName);
094        I18nizableText label = ItemParserHelper.parseI18nizableText(checkerConfigAndPluginName, "label");
095        I18nizableText description = ItemParserHelper.parseI18nizableText(checkerConfigAndPluginName, "description");
096        
097        Configuration uiRefConfig = paramCheckerConfig.getChild("ui-ref");
098        int uiRefOrder = uiRefConfig.getChild("order").getValueAsInteger(1);
099        
100        String uiRefLocation = null;
101        Configuration uiRefLocationConfig = uiRefConfig.getChild("location", false);
102        if (uiRefLocationConfig != null)
103        {
104            uiRefLocation = uiRefLocationConfig.getAttribute("path");
105        }
106        
107        Set<String >linkedParamsPaths = new LinkedHashSet<>();
108        for (Configuration linkedParamConfig : paramCheckerConfig.getChild("linked-params").getChildren("param-ref"))
109        {
110            linkedParamsPaths.add(linkedParamConfig.getAttribute("id"));
111        }
112        
113        parameterChecker.setName(parameterId);
114        parameterChecker.setLabel(label);
115        parameterChecker.setDescription(description);
116        parameterChecker.setClass(concreteClass);
117        parameterChecker.setSmallIconPath(smallIconPath);
118        parameterChecker.setMediumIconPath(mediumIconPath);
119        parameterChecker.setLargeIconPath(largeIconPath);
120        parameterChecker.setUiRefOrder(uiRefOrder);
121        parameterChecker.setUiRefLocation(uiRefLocation);
122
123        parameterChecker.setLinkedParamsPaths(linkedParamsPaths);
124        
125        _setParameterChecker(pluginName, parameterChecker, parameterId, paramCheckerConfig);
126        return parameterChecker;
127    }
128    
129    /**
130     * Sets the parameter checker.
131     * @param pluginName the plugin's name.
132     * @param parameterChecker the parameter checker.
133     * @param parameterCheckerId the parameter chekcer's id.
134     * @param parameterCheckerConfig the parameter checker's configuration.
135     * @throws ConfigurationException if the configuration is not valid.
136     */
137    @SuppressWarnings("unchecked")
138    protected void _setParameterChecker(String pluginName, ItemCheckerDescriptor parameterChecker, String parameterCheckerId, Configuration parameterCheckerConfig) throws ConfigurationException
139    {
140        if (parameterCheckerConfig != null)
141        {
142            String parameterCheckerClassName = parameterCheckerConfig.getAttribute("class");
143            
144            try
145            {
146                Class parameterCheckerClass = Class.forName(parameterCheckerClassName);
147                _parameterCheckerManager.addComponent(pluginName, null, parameterCheckerId, parameterCheckerClass, parameterCheckerConfig);
148            }
149            catch (Exception e)
150            {
151                throw new ConfigurationException("Unable to instantiate parameter checker for class: " + parameterCheckerClassName, e);
152            }
153
154            // Will be affected later when parameterCheckerManager will be initialized
155            // in lookupComponents() call
156            _parameterCheckersToLookup.put(parameterChecker, parameterCheckerId);
157        }
158    }
159    
160    /**
161     * Retrieves local parameter checkers components and sets them into
162     * the previous parameter checker parsed.
163     * @throws Exception if an error occurs.
164     */
165    public void lookupComponents() throws Exception
166    {
167        _parameterCheckerManager.initialize();
168        
169        for (Map.Entry<ItemCheckerDescriptor, String> entry : _parameterCheckersToLookup.entrySet())
170        {
171            ItemCheckerDescriptor parameterChecker = entry.getKey();
172            String parameterCheckerRole = entry.getValue();
173            
174            try
175            {
176                parameterChecker.setParameterChecker(_parameterCheckerManager.lookup(parameterCheckerRole));
177            }
178            catch (ComponentException e)
179            {
180                throw new Exception("Unable to lookup parameter checker role: '" + parameterCheckerRole + "' for parameter: " + parameterChecker, e);
181            }
182        }
183    }
184    
185    /**
186     * Get the parameter checker descriptor instance to use
187     * @return the parameter checker descriptor instance to use
188     */
189    protected ItemCheckerDescriptor _getParameterCheckerDescriptorInstance()
190    {
191        return new ItemCheckerDescriptor();
192    }
193}