001/* 002 * Copyright 2018 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; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.UUID; 021 022import org.apache.avalon.framework.component.ComponentException; 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.commons.lang3.StringUtils; 027 028import org.ametys.runtime.i18n.I18nizableText; 029import org.ametys.runtime.model.disableconditions.DisableConditions; 030import org.ametys.runtime.model.exception.UnknownTypeException; 031import org.ametys.runtime.model.type.ModelItemType; 032import org.ametys.runtime.model.type.ModelItemTypeExtensionPoint; 033import org.ametys.runtime.plugin.component.ThreadSafeComponentManager; 034import org.ametys.runtime.util.ParameterizedTypesHelper; 035 036/** 037 * {@link ModelItem} parser from an XML configuration. 038 * @param <D> The type of disable conditions managed by the parsed item 039 */ 040@SuppressWarnings("unchecked") 041public abstract class AbstractModelItemParser<D extends DisableConditions> 042{ 043 /** The extension point to use to get available model items types */ 044 protected ModelItemTypeExtensionPoint _modelItemTypeExtensionPoint; 045 046 /** The disable conditions component manager */ 047 protected ThreadSafeComponentManager<DisableConditions> _disableConditionsManager; 048 /** The disabled conditions to lookup */ 049 protected final Map<String, ModelItem> _disableConditionsToLookup = new HashMap<>(); 050 051 private Class<D> _disableConditionsType; 052 { 053 _disableConditionsType = ParameterizedTypesHelper.getFirstActualClassArgument(AbstractModelItemParser.class, this.getClass()); 054 } 055 056 /** 057 * Creates a model item parser. 058 * @param modelItemTypeExtensionPoint the extension point to use to get available model items types 059 * @param disableConditionsManager the disable conditions component manager 060 */ 061 public AbstractModelItemParser(ModelItemTypeExtensionPoint modelItemTypeExtensionPoint, ThreadSafeComponentManager<DisableConditions> disableConditionsManager) 062 { 063 _modelItemTypeExtensionPoint = modelItemTypeExtensionPoint; 064 _disableConditionsManager = disableConditionsManager; 065 } 066 067 /** 068 * Parses an element definition from a XML configuration. 069 * @param <T> type of the parsed item 070 * @param serviceManager the service manager 071 * @param pluginName the plugin name declaring this item. 072 * @param itemConfig the XML configuration of the model item. 073 * @param model the model which defines the model item 074 * @param parent the parent of the model item to create. Can be null if the model item to parse has no parent 075 * @return the parsed model item. 076 * @throws ConfigurationException if the configuration is not valid. 077 */ 078 public <T extends ModelItem> T parse(ServiceManager serviceManager, String pluginName, Configuration itemConfig, Model model, ModelItemGroup parent) throws ConfigurationException 079 { 080 return (T) parse(serviceManager, pluginName, "plugin." + pluginName, itemConfig, model, parent); 081 } 082 083 /** 084 * Parses an element definition from a XML configuration. 085 * @param <T> type of the parsed item 086 * @param serviceManager the service manager 087 * @param pluginName the plugin name declaring this item. 088 * @param catalog the catalog 089 * @param itemConfig the XML configuration of the model item. 090 * @param model the model which defines the model item 091 * @param parent the parent of the model item to create. Can be null if the model item to parse has no parent 092 * @return the parsed model item. 093 * @throws ConfigurationException if the configuration is not valid. 094 */ 095 public <T extends ModelItem> T parse(ServiceManager serviceManager, String pluginName, String catalog, Configuration itemConfig, Model model, ModelItemGroup parent) throws ConfigurationException 096 { 097 ModelItem modelItem = _createModelItem(itemConfig); 098 099 modelItem.setModel(model); 100 if (parent != null) 101 { 102 parent.addChild(modelItem); 103 } 104 105 modelItem.setName(_parseName(itemConfig)); 106 modelItem.setPluginName(pluginName); 107 modelItem.setLabel(_parseI18nizableText(itemConfig, catalog, "label")); 108 modelItem.setDescription(_parseI18nizableText(itemConfig, catalog, "description")); 109 modelItem.setType(_parseType(itemConfig)); 110 111 modelItem.setWidget(_parseWidget(itemConfig)); 112 modelItem.setWidgetParameters(_parseWidgetParameters(itemConfig, pluginName)); 113 114 _parseDisableConditions(itemConfig, pluginName, modelItem); 115 116 return (T) modelItem; 117 } 118 119 /** 120 * Create the model item to populate it. 121 * @param itemConfig the model item configuration to use. 122 * @return the item instantiated. 123 * @throws ConfigurationException if the configuration is not valid. 124 */ 125 protected abstract ModelItem _createModelItem(Configuration itemConfig) throws ConfigurationException; 126 127 /** 128 * Parses the name of the model item. 129 * @param itemConfig the model item configuration to use. 130 * @return the name of the model item. 131 * @throws ConfigurationException if the configuration is not valid. 132 */ 133 protected String _parseName(Configuration itemConfig) throws ConfigurationException 134 { 135 return ItemParserHelper.parseName(itemConfig, _getNameConfigurationAttribute()); 136 } 137 138 /** 139 * Retrieves the name of the configuration attribute that contains the name of the model item 140 * @return the name of the configuration attribute that contains the name of the model item 141 */ 142 protected String _getNameConfigurationAttribute() 143 { 144 return "name"; 145 } 146 147 /** 148 * Parses a mandatory i18n text configuration, throwing an exception if empty. 149 * @param config the configuration to use. 150 * @param catalog the catalog 151 * @param name the child name. 152 * @return the i18n text. 153 * @throws ConfigurationException if the configuration is not valid. 154 */ 155 protected I18nizableText _parseI18nizableText(Configuration config, String catalog, String name) throws ConfigurationException 156 { 157 return I18nizableText.parseI18nizableText(config.getChild(name), catalog); 158 } 159 160 /** 161 * Parse an optional i18n text configuration, with a default i18n text value. 162 * @param config the configuration to use. 163 * @param catalog the catalog 164 * @param name the child name. 165 * @param defaultValueCatalog the catalog of the default i18n text value 166 * @param defaultValue the default i18n text value. 167 * @return the i18n text. 168 */ 169 protected I18nizableText _parseI18nizableText(Configuration config, String catalog, String name, String defaultValueCatalog, String defaultValue) 170 { 171 return I18nizableText.parseI18nizableText(config.getChild(name), catalog, new I18nizableText(defaultValueCatalog, defaultValue)); 172 } 173 174 /** 175 * Parses the type. 176 * @param config the model item configuration to use. 177 * @return the type. 178 * @throws ConfigurationException if the configuration is not valid. 179 */ 180 protected ModelItemType _parseType(Configuration config) throws ConfigurationException 181 { 182 String typeId = config.getAttribute("type"); 183 184 if (!_modelItemTypeExtensionPoint.hasExtension(typeId)) 185 { 186 String modelItemName = _parseName(config); 187 String availableTypes = StringUtils.join(_modelItemTypeExtensionPoint.getExtensionsIds(), ", "); 188 UnknownTypeException ute = new UnknownTypeException("The type '" + typeId + "' is not available for the extension point '" + _modelItemTypeExtensionPoint + "'. Available types are: '" + availableTypes + "'."); 189 throw new ConfigurationException("Unable to find the type '" + typeId + "' defined on the item '" + modelItemName + "'.", ute); 190 } 191 192 return _modelItemTypeExtensionPoint.getExtension(typeId); 193 } 194 195 /** 196 * Parses the disable conditions. 197 * @param pluginName the plugin name. 198 * @param modelItem the model item. 199 * @param definitionConfiguration the configuration of the model item 200 * @throws ConfigurationException if an error occurred 201 */ 202 protected void _parseDisableConditions(Configuration definitionConfiguration, String pluginName, ModelItem modelItem) throws ConfigurationException 203 { 204 Configuration disableConditionsConfiguration = definitionConfiguration.getChild("disable-conditions", false); 205 if (disableConditionsConfiguration != null) 206 { 207 Class<? extends DisableConditions> conditionsClass = _disableConditionsType; 208 final String conditionsRole = conditionsClass + "$" + UUID.randomUUID().toString(); 209 _disableConditionsManager.addComponent(pluginName, null, conditionsRole, conditionsClass, disableConditionsConfiguration); 210 _disableConditionsToLookup.put(conditionsRole, modelItem); 211 } 212 } 213 214 /** 215 * Parses the widget. 216 * @param definitionConfig the element definition configuration to use. 217 * @return the widget or <code>null</code> if none defined. 218 * @throws ConfigurationException if the configuration is not valid. 219 */ 220 protected String _parseWidget(Configuration definitionConfig) throws ConfigurationException 221 { 222 return ItemParserHelper.parseWidget(definitionConfig); 223 } 224 225 /** 226 * Parses the widget's parameters 227 * @param definitionConfig the parameter ele;ent definition to use. 228 * @param pluginName the current plugin name. 229 * @return the widget's parameters in a Map 230 * @throws ConfigurationException if the configuration is not valid. 231 */ 232 protected Map<String, I18nizableText> _parseWidgetParameters(Configuration definitionConfig, String pluginName) throws ConfigurationException 233 { 234 return ItemParserHelper.parseWidgetParameters(definitionConfig, pluginName); 235 } 236 237 /** 238 * Retrieves components and set them into previous parsed model item. 239 * @throws Exception if an error occurs. 240 */ 241 public void lookupComponents() throws Exception 242 { 243 _disableConditionsManager.initialize(); 244 245 for (Map.Entry<String, ModelItem> entry : _disableConditionsToLookup.entrySet()) 246 { 247 String conditionsRole = entry.getKey(); 248 ModelItem modelItem = entry.getValue(); 249 250 try 251 { 252 modelItem.setDisableConditions(_disableConditionsManager.lookup(conditionsRole)); 253 } 254 catch (ComponentException e) 255 { 256 throw new Exception("Unable to lookup disable conditions role: '" + conditionsRole + "' for parameter: " + modelItem, e); 257 } 258 } 259 } 260}