001/* 002 * Copyright 2012 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.parameter; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.avalon.framework.component.ComponentException; 022import org.apache.avalon.framework.configuration.Configuration; 023import org.apache.avalon.framework.configuration.ConfigurationException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.commons.lang3.StringUtils; 026 027import org.ametys.runtime.i18n.I18nizableText; 028import org.ametys.runtime.plugin.component.ThreadSafeComponentManager; 029 030/** 031 * {@link Parameter} parser from an XML configuration. 032 * @param <P> the actual type of parameter. 033 * @param <T> the actual type of parameter type. 034 */ 035public abstract class AbstractParameterParser<P extends Parameter<T>, T> 036{ 037 /** The enumerators component manager. */ 038 protected ThreadSafeComponentManager<Enumerator> _enumeratorManager; 039 /** The validators component manager. */ 040 protected ThreadSafeComponentManager<Validator> _validatorManager; 041 private final Map<P, String> _validatorsToLookup = new HashMap<>(); 042 private final Map<P, String> _enumeratorsToLookup = new HashMap<>(); 043 044 /** 045 * Creates an AbstractParameterParser. 046 * @param enumeratorManager the enumerator component manager. 047 * @param validatorManager the validator component manager. 048 */ 049 public AbstractParameterParser(ThreadSafeComponentManager<Enumerator> enumeratorManager, ThreadSafeComponentManager<Validator> validatorManager) 050 { 051 _enumeratorManager = enumeratorManager; 052 _validatorManager = validatorManager; 053 } 054 055 /** 056 * Parses a parameter from a XML configuration. 057 * @param manager the service manager. 058 * @param pluginName the plugin name declaring this parameter. 059 * @param parameterConfig the XML configuration. 060 * @return the parsed parameter. 061 * @throws ConfigurationException if the configuration is not valid. 062 */ 063 public P parseParameter(ServiceManager manager, String pluginName, Configuration parameterConfig) throws ConfigurationException 064 { 065 P parameter = _createParameter(parameterConfig); 066 String parameterId = _parseId(parameterConfig); 067 068 parameter.setId(parameterId); 069 parameter.setPluginName(pluginName); 070 parameter.setLabel(_parseI18nizableText(parameterConfig, pluginName, "label")); 071 parameter.setDescription(_parseI18nizableText(parameterConfig, pluginName, "description")); 072 parameter.setType(_parseType(parameterConfig)); 073 parameter.setWidget(_parseWidget(parameterConfig)); 074 parameter.setWidgetParameters(_parseWidgetParameters(parameterConfig, pluginName)); 075 _parseAndSetEnumerator(pluginName, parameter, parameterId, parameterConfig); 076 _parseAndSetValidator(pluginName, parameter, parameterId, parameterConfig); 077 parameter.setDefaultValue(_parseDefaultValue(parameterConfig, parameter)); 078 079 _additionalParsing(manager, pluginName, parameterConfig, parameterId, parameter); 080 081 return parameter; 082 } 083 084 /** 085 * Retrieves local validators and enumerators components and set them into 086 * previous parameter parsed. 087 * @throws Exception if an error occurs. 088 */ 089 public void lookupComponents() throws Exception 090 { 091 _validatorManager.initialize(); 092 _enumeratorManager.initialize(); 093 094 for (Map.Entry<P, String> entry : _validatorsToLookup.entrySet()) 095 { 096 P parameter = entry.getKey(); 097 String validatorRole = entry.getValue(); 098 099 try 100 { 101 parameter.setValidator(_validatorManager.lookup(validatorRole)); 102 } 103 catch (ComponentException e) 104 { 105 throw new Exception("Unable to lookup validator role: '" + validatorRole + "' for parameter: " + parameter, e); 106 } 107 } 108 109 for (Map.Entry<P, String> entry : _enumeratorsToLookup.entrySet()) 110 { 111 P parameter = entry.getKey(); 112 String enumeratorRole = entry.getValue(); 113 114 try 115 { 116 parameter.setEnumerator(_enumeratorManager.lookup(enumeratorRole)); 117 } 118 catch (ComponentException e) 119 { 120 throw new Exception("Unable to lookup enumerator role: '" + enumeratorRole + "' for parameter: " + parameter, e); 121 } 122 } 123 } 124 125 /** 126 * Create the parameter to populate it. 127 * @param parameterConfig the parameter configuration to use. 128 * @return the parameter instantiated. 129 * @throws ConfigurationException if the configuration is not valid. 130 */ 131 protected abstract P _createParameter(Configuration parameterConfig) throws ConfigurationException; 132 133 /** 134 * Parses the id. 135 * @param parameterConfig the parameter configuration to use. 136 * @return the id. 137 * @throws ConfigurationException if the configuration is not valid. 138 */ 139 protected abstract String _parseId(Configuration parameterConfig) throws ConfigurationException; 140 141 /** 142 * Parses an i18n text. 143 * @param config the configuration to use. 144 * @param pluginName the current plugin name. 145 * @param name the child name. 146 * @return the i18n text. 147 * @throws ConfigurationException if the configuration is not valid. 148 */ 149 protected I18nizableText _parseI18nizableText(Configuration config, String pluginName, String name) throws ConfigurationException 150 { 151 return I18nizableText.parseI18nizableText(config.getChild(name), "plugin." + pluginName); 152 } 153 154 /** 155 * Parses the type. 156 * @param parameterConfig the parameter configuration to use. 157 * @return the type. 158 * @throws ConfigurationException if the configuration is not valid. 159 */ 160 protected abstract T _parseType(Configuration parameterConfig) throws ConfigurationException; 161 162 /** 163 * Parses the widget. 164 * @param parameterConfig the parameter configuration to use. 165 * @return the widget or <code>null</code> if none defined. 166 * @throws ConfigurationException if the configuration is not valid. 167 */ 168 protected String _parseWidget(Configuration parameterConfig) throws ConfigurationException 169 { 170 return parameterConfig.getChild("widget").getValue(null); 171 } 172 173 /** 174 * Parses the widget's parameters 175 * @param parameterConfig the parameter configuration to use. 176 * @param pluginName the current plugin name. 177 * @return the widget's parameters in a Map 178 * @throws ConfigurationException if the configuration is not valid. 179 */ 180 protected Map<String, I18nizableText> _parseWidgetParameters(Configuration parameterConfig, String pluginName) throws ConfigurationException 181 { 182 Map<String, I18nizableText> widgetParams = new HashMap<>(); 183 184 Configuration widgetParamsConfig = parameterConfig.getChild("widget-params", false); 185 if (widgetParamsConfig != null) 186 { 187 Configuration[] params = widgetParamsConfig.getChildren("param"); 188 for (Configuration paramConfig : params) 189 { 190 boolean i18nSupported = paramConfig.getAttributeAsBoolean("i18n", false); 191 if (i18nSupported) 192 { 193 String catalogue = paramConfig.getAttribute("catalogue", null); 194 195 if (catalogue == null) 196 { 197 catalogue = "plugin." + pluginName; 198 } 199 200 widgetParams.put(paramConfig.getAttribute("name"), new I18nizableText(catalogue, paramConfig.getValue())); 201 } 202 else 203 { 204 widgetParams.put(paramConfig.getAttribute("name"), new I18nizableText(paramConfig.getValue(""))); 205 } 206 } 207 } 208 209 return widgetParams; 210 } 211 212 /** 213 * Parses the enumerator. 214 * @param pluginName the plugin name. 215 * @param parameter the parameter. 216 * @param parameterId the parameter id. 217 * @param parameterConfig the parameter configuration. 218 * @throws ConfigurationException if the configuration is not valid. 219 */ 220 @SuppressWarnings("unchecked") 221 protected void _parseAndSetEnumerator(String pluginName, P parameter, String parameterId, Configuration parameterConfig) throws ConfigurationException 222 { 223 Configuration enumeratorConfig = parameterConfig.getChild("enumeration", false); 224 225 if (enumeratorConfig != null) 226 { 227 Configuration customEnumerator = enumeratorConfig.getChild("custom-enumerator", false); 228 229 if (customEnumerator != null) 230 { 231 String enumeratorClassName = customEnumerator.getAttribute("class"); 232 233 try 234 { 235 Class enumeratorClass = Class.forName(enumeratorClassName); 236 _enumeratorManager.addComponent(pluginName, null, parameterId, enumeratorClass, parameterConfig); 237 } 238 catch (Exception e) 239 { 240 throw new ConfigurationException("Unable to instantiate enumerator for class: " + enumeratorClassName, e); 241 } 242 243 // This enumerator will be affected later when validatorManager 244 // will be initialized in lookupComponents() call 245 _enumeratorsToLookup.put(parameter, parameterId); 246 247 } 248 else 249 { 250 StaticEnumerator staticEnumerator = new StaticEnumerator(); 251 252 for (Configuration entryConfig : enumeratorConfig.getChildren("entry")) 253 { 254 String value = entryConfig.getChild("value").getValue(""); 255 I18nizableText label = null; 256 257 if (entryConfig.getChild("label", false) != null) 258 { 259 label = _parseI18nizableText(entryConfig, pluginName, "label"); 260 } 261 262 staticEnumerator.add(label, value); 263 } 264 265 parameter.setEnumerator(staticEnumerator); 266 } 267 } 268 } 269 270 /** 271 * Parses the validator. 272 * @param pluginName the plugin name. 273 * @param parameter the parameter. 274 * @param parameterId the parameter id. 275 * @param parameterConfig the parameter configuration. 276 * @throws ConfigurationException if the configuration is not valid. 277 */ 278 @SuppressWarnings("unchecked") 279 protected void _parseAndSetValidator(String pluginName, P parameter, String parameterId, Configuration parameterConfig) throws ConfigurationException 280 { 281 Configuration validatorConfig = parameterConfig.getChild("validation", false); 282 283 if (validatorConfig != null) 284 { 285 String validatorClassName = StringUtils.defaultIfBlank(validatorConfig.getChild("custom-validator").getAttribute("class", ""), DefaultValidator.class.getName()); 286 287 try 288 { 289 Class validatorClass = Class.forName(validatorClassName); 290 _validatorManager.addComponent(pluginName, null, parameterId, validatorClass, parameterConfig); 291 } 292 catch (Exception e) 293 { 294 throw new ConfigurationException("Unable to instantiate validator for class: " + validatorClassName, e); 295 } 296 297 // Will be affected later when validatorManager will be initialized 298 // in lookupComponents() call 299 _validatorsToLookup.put(parameter, parameterId); 300 } 301 } 302 303 /** 304 * Parses the default value. 305 * @param parameterConfig the parameter configuration. 306 * @param parameter the parameter. 307 * @return the default value or <code>null</code> if none defined. 308 * @throws ConfigurationException if the configuration is not valid. 309 */ 310 protected abstract Object _parseDefaultValue(Configuration parameterConfig, P parameter) throws ConfigurationException; 311 312 /** 313 * Called for additional parsing.<br> 314 * Default implementation does nothing. 315 * @param manager the sservice manager. 316 * @param pluginName the plugin name. 317 * @param parameterConfig the parameter configuration. 318 * @param parameterId the parameter id. 319 * @param parameter the parameter to populate. 320 * @throws ConfigurationException if the configuration is not valid. 321 */ 322 protected void _additionalParsing(ServiceManager manager, String pluginName, Configuration parameterConfig, String parameterId, P parameter) throws ConfigurationException 323 { 324 // Nothing to do 325 } 326}