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; 034 035/** 036 * {@link ModelItem} parser from an XML configuration. 037 */ 038public abstract class AbstractModelItemParser 039{ 040 /** The extension point to use to get available model items types */ 041 protected ModelItemTypeExtensionPoint _modelItemTypeExtensionPoint; 042 043 /** The disable conditions component manager */ 044 protected ThreadSafeComponentManager<DisableConditions> _disableConditionsManager; 045 /** The disabled conditions to lookup */ 046 protected final Map<String, ModelItem> _disableConditionsToLookup = new HashMap<>(); 047 048 /** 049 * Creates a model item parser. 050 * @param modelItemTypeExtensionPoint the extension point to use to get available model items types 051 * @param disableConditionsManager the disable conditions component manager 052 */ 053 public AbstractModelItemParser(ModelItemTypeExtensionPoint modelItemTypeExtensionPoint, ThreadSafeComponentManager<DisableConditions> disableConditionsManager) 054 { 055 _modelItemTypeExtensionPoint = modelItemTypeExtensionPoint; 056 _disableConditionsManager = disableConditionsManager; 057 } 058 059 /** 060 * Parses an element definition from a XML configuration. 061 * @param <T> type of the parsed item 062 * @param serviceManager the service manager 063 * @param pluginName the plugin name declaring this item. 064 * @param itemConfig the XML configuration of the model item. 065 * @param model the model which defines the model item 066 * @param parent the parent of the model item to create. Can be null if the model item to parse has no parent 067 * @return the parsed model item. 068 * @throws ConfigurationException if the configuration is not valid. 069 */ 070 @SuppressWarnings("unchecked") 071 public <T extends ModelItem> T parse(ServiceManager serviceManager, String pluginName, Configuration itemConfig, Model model, ModelItemGroup parent) throws ConfigurationException 072 { 073 return (T) parse(serviceManager, pluginName, "plugin." + pluginName, itemConfig, model, parent); 074 } 075 076 /** 077 * Parses an element definition from a XML configuration. 078 * @param <T> type of the parsed item 079 * @param serviceManager the service manager 080 * @param pluginName the plugin name declaring this item. 081 * @param catalog the catalog 082 * @param itemConfig the XML configuration of the model item. 083 * @param model the model which defines the model item 084 * @param parent the parent of the model item to create. Can be null if the model item to parse has no parent 085 * @return the parsed model item. 086 * @throws ConfigurationException if the configuration is not valid. 087 */ 088 @SuppressWarnings("unchecked") 089 public <T extends ModelItem> T parse(ServiceManager serviceManager, String pluginName, String catalog, Configuration itemConfig, Model model, ModelItemGroup parent) throws ConfigurationException 090 { 091 ModelItem modelItem = _createModelItem(itemConfig); 092 093 modelItem.setModel(model); 094 if (parent != null) 095 { 096 parent.addChild(modelItem); 097 } 098 099 modelItem.setName(_parseName(itemConfig)); 100 modelItem.setPluginName(pluginName); 101 modelItem.setLabel(_parseI18nizableText(itemConfig, catalog, "label")); 102 modelItem.setDescription(_parseI18nizableText(itemConfig, catalog, "description")); 103 modelItem.setType(_parseType(itemConfig)); 104 105 modelItem.setWidget(_parseWidget(itemConfig)); 106 modelItem.setWidgetParameters(_parseWidgetParameters(itemConfig, pluginName)); 107 108 _parseDisableConditions(itemConfig, pluginName, modelItem); 109 110 return (T) modelItem; 111 } 112 113 /** 114 * Create the model item to populate it. 115 * @param itemConfig the model item configuration to use. 116 * @return the item instantiated. 117 * @throws ConfigurationException if the configuration is not valid. 118 */ 119 protected abstract ModelItem _createModelItem(Configuration itemConfig) throws ConfigurationException; 120 121 /** 122 * Parses the name of the model item. 123 * @param itemConfig the model item configuration to use. 124 * @return the name of the model item. 125 * @throws ConfigurationException if the configuration is not valid. 126 */ 127 protected String _parseName(Configuration itemConfig) throws ConfigurationException 128 { 129 return ItemParserHelper.parseName(itemConfig, _getNameConfigurationAttribute()); 130 } 131 132 /** 133 * Retrieves the name of the configuration attribute that contains the name of the model item 134 * @return the name of the configuration attribute that contains the name of the model item 135 */ 136 protected String _getNameConfigurationAttribute() 137 { 138 return "name"; 139 } 140 141 /** 142 * Parses a mandatory i18n text configuration, throwing an exception if empty. 143 * @param config the configuration to use. 144 * @param catalog the catalog 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 catalog, String name) throws ConfigurationException 150 { 151 return I18nizableText.parseI18nizableText(config.getChild(name), catalog); 152 } 153 154 /** 155 * Parse an optional i18n text configuration, with a default i18n text value. 156 * @param config the configuration to use. 157 * @param catalog the catalog 158 * @param name the child name. 159 * @param defaultValueCatalog the catalog of the default i18n text value 160 * @param defaultValue the default i18n text value. 161 * @return the i18n text. 162 */ 163 protected I18nizableText _parseI18nizableText(Configuration config, String catalog, String name, String defaultValueCatalog, String defaultValue) 164 { 165 return I18nizableText.parseI18nizableText(config.getChild(name), catalog, new I18nizableText(defaultValueCatalog, defaultValue)); 166 } 167 168 /** 169 * Parses the type. 170 * @param config the model item configuration to use. 171 * @return the type. 172 * @throws ConfigurationException if the configuration is not valid. 173 */ 174 protected ModelItemType _parseType(Configuration config) throws ConfigurationException 175 { 176 String typeId = config.getAttribute("type"); 177 178 if (!_modelItemTypeExtensionPoint.hasExtension(typeId)) 179 { 180 String modelItemName = _parseName(config); 181 String availableTypes = StringUtils.join(_modelItemTypeExtensionPoint.getExtensionsIds(), ", "); 182 UnknownTypeException ute = new UnknownTypeException("The type '" + typeId + "' is not available for the extension point '" + _modelItemTypeExtensionPoint + "'. Available types are: '" + availableTypes + "'."); 183 throw new ConfigurationException("Unable to find the type '" + typeId + "' defined on the item '" + modelItemName + "'.", ute); 184 } 185 186 return _modelItemTypeExtensionPoint.getExtension(typeId); 187 } 188 189 /** 190 * Parses the disable conditions. 191 * @param pluginName the plugin name. 192 * @param modelItem the model item. 193 * @param definitionConfiguration the configuration of the model item 194 * @throws ConfigurationException if an error occurred 195 */ 196 protected void _parseDisableConditions(Configuration definitionConfiguration, String pluginName, ModelItem modelItem) throws ConfigurationException 197 { 198 Configuration disableConditionsConfiguration = definitionConfiguration.getChild("disable-conditions", false); 199 if (disableConditionsConfiguration != null) 200 { 201 Class<? extends DisableConditions> conditionsClass = getDisableConditionsClass(); 202 final String conditionsRole = conditionsClass + "$" + UUID.randomUUID().toString(); 203 _disableConditionsManager.addComponent(pluginName, null, conditionsRole, conditionsClass, disableConditionsConfiguration); 204 _disableConditionsToLookup.put(conditionsRole, modelItem); 205 } 206 } 207 208 /** 209 * Retrieves the class of {@link DisableConditions} to create 210 * @return the class of {@link DisableConditions} to create 211 */ 212 protected abstract Class<? extends DisableConditions> getDisableConditionsClass(); 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}