001/* 002 * Copyright 2020 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.web.parameters; 017 018import java.util.LinkedHashMap; 019import java.util.Map; 020 021import org.apache.avalon.framework.component.Component; 022import org.apache.avalon.framework.configuration.Configuration; 023import org.apache.avalon.framework.configuration.ConfigurationException; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.avalon.framework.service.Serviceable; 027import org.apache.commons.lang.StringUtils; 028 029import org.ametys.plugins.repository.model.RepeaterDefinition; 030import org.ametys.plugins.repository.model.parsing.RepeaterDefinitionParser; 031import org.ametys.runtime.i18n.I18nizableText; 032import org.ametys.runtime.model.ElementDefinition; 033import org.ametys.runtime.model.ElementDefinitionParser; 034import org.ametys.runtime.model.Model; 035import org.ametys.runtime.model.ModelItem; 036import org.ametys.runtime.model.ModelItemGroup; 037import org.ametys.runtime.model.ModelViewItem; 038import org.ametys.runtime.model.ModelViewItemGroup; 039import org.ametys.runtime.model.SimpleViewItemGroup; 040import org.ametys.runtime.model.View; 041import org.ametys.runtime.model.ViewElement; 042import org.ametys.runtime.model.ViewItem; 043import org.ametys.runtime.model.ViewItemContainer; 044import org.ametys.runtime.model.ViewItemGroup; 045import org.ametys.runtime.plugin.component.AbstractLogEnabled; 046 047/** 048 * Helper to parse parameters from configuration 049 */ 050public class ViewAndParametersParser extends AbstractLogEnabled implements Component, Serviceable 051{ 052 /** Avalon Role */ 053 public static final String ROLE = ViewAndParametersParser.class.getName(); 054 055 /** The service manager */ 056 protected ServiceManager _manager; 057 058 @Override 059 public void service(ServiceManager smanager) throws ServiceException 060 { 061 _manager = smanager; 062 } 063 064 /** 065 * Parse the configuration to get parameters. 066 * @param parametersConfiguration the parameters configuration. 067 * @param pluginName the plugin name 068 * @param catalog the catalog 069 * @param model the model 070 * @param elementDefinitionParser the element definition parser 071 * @param repeaterDefinitionParser the repeater definition parser 072 * @return the parameters 073 * @throws ConfigurationException if an error occurs. 074 */ 075 public ViewAndParameters parseParameters(Configuration parametersConfiguration, String pluginName, String catalog, Model model, ElementDefinitionParser elementDefinitionParser, RepeaterDefinitionParser repeaterDefinitionParser) throws ConfigurationException 076 { 077 View view = new View(); 078 Map<String, ModelItem> modelItems = new LinkedHashMap<>(); 079 080 view.setName(parametersConfiguration.getAttribute("name", null)); 081 view.setLabel(_parseI18nizableText(parametersConfiguration, "label", pluginName, catalog)); 082 view.setDescription(_parseI18nizableText(parametersConfiguration, "description", pluginName, catalog)); 083 084 // Parse all groups, fielsets and parameters to build the view 085 Configuration[] groupConfigurations = parametersConfiguration.getChildren("group"); 086 if (groupConfigurations.length > 0) 087 { 088 if (parametersConfiguration.getChildren("fieldset").length > 0 089 || parametersConfiguration.getChildren("parameter").length > 0 090 || parametersConfiguration.getChildren("repeater").length > 0) 091 { 092 throw new ConfigurationException("This parameters configuration should not have parameters out of its groups.", parametersConfiguration); 093 } 094 095 // Has groups. 096 for (Configuration groupConfiguration : groupConfigurations) 097 { 098 SimpleViewItemGroup group = _parseSimpleViewItemGroup(groupConfiguration, null, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 099 group.setRole(ViewItemGroup.TAB_ROLE); 100 view.addViewItem(group); 101 } 102 } 103 else 104 { 105 _parseChildren(parametersConfiguration, view, null, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 106 } 107 108 return new ViewAndParameters(view, modelItems); 109 } 110 111 /** 112 * Parses a simple view item group (group or fieldset) 113 * @param groupConfiguration the item group configuration 114 * @param modelParent The last model item group to use as parent for next definitions 115 * @param pluginName the plugin name 116 * @param catalog the catalog 117 * @param view the view 118 * @param modelItems the map of model items 119 * @param model the model 120 * @param elementDefinitionParser the element definition parser 121 * @param repeaterDefinitionParser the repeater definition parser 122 * @return the parsed simple view item group 123 * @throws ConfigurationException if an error occurs 124 */ 125 protected SimpleViewItemGroup _parseSimpleViewItemGroup(Configuration groupConfiguration, ModelItemGroup modelParent, String pluginName, String catalog, View view, Map<String, ModelItem> modelItems, Model model, ElementDefinitionParser elementDefinitionParser, RepeaterDefinitionParser repeaterDefinitionParser) throws ConfigurationException 126 { 127 SimpleViewItemGroup group = new SimpleViewItemGroup(); 128 group.setName(groupConfiguration.getAttribute("name", null)); 129 group.setLabel(_parseI18nizableText(groupConfiguration, "label", pluginName, catalog)); 130 group.setDescription(_parseI18nizableText(groupConfiguration, "description", pluginName, catalog)); 131 132 _parseChildren(groupConfiguration, group, modelParent, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 133 134 return group; 135 } 136 137 /** 138 * Parses a service parameter 139 * @param paramConfiguration the parameter configuration 140 * @param parent the parent of the service parameter. Can be <code>null</code> if the parameter has no parent 141 * @param pluginName the plugin name 142 * @param catalog the catalog 143 * @param view the view 144 * @param modelItems the map of model item 145 * @param model the model 146 * @param elementDefinitionParser the element definition parser 147 * @param repeaterDefinitionParser the repeater definition parser 148 * @return the parsed parameter 149 * @throws ConfigurationException if an error occurs 150 */ 151 public ViewElement parseParameter(Configuration paramConfiguration, ModelItemGroup parent, String pluginName, String catalog, View view, Map<String, ModelItem> modelItems, Model model, ElementDefinitionParser elementDefinitionParser, RepeaterDefinitionParser repeaterDefinitionParser) throws ConfigurationException 152 { 153 ElementDefinition elementParameter = elementDefinitionParser.parse(_manager, pluginName, catalog, paramConfiguration, model, parent); 154 155 if (elementParameter != null) 156 { 157 ViewElement viewElement = new ViewElement(); 158 viewElement.setDefinition(elementParameter); 159 160 return viewElement; 161 } 162 163 return null; 164 } 165 166 /** 167 * Parses a repeater 168 * @param repeaterConfiguration the repeater configuration 169 * @param parent the parent of the repeater. Can be <code>null</code> if the repeater has no parent 170 * @param pluginName the plugin name 171 * @param catalog the catalog 172 * @param view the view 173 * @param modelItems the map of model item 174 * @param model the model 175 * @param elementDefinitionParser the element definition parser 176 * @param repeaterDefinitionParser the repeater definition parser 177 * @return the parsed repeater 178 * @throws ConfigurationException if an error occurs 179 */ 180 public ModelViewItemGroup parseRepeater(Configuration repeaterConfiguration, ModelItemGroup parent, String pluginName, String catalog, View view, Map<String, ModelItem> modelItems, Model model, ElementDefinitionParser elementDefinitionParser, RepeaterDefinitionParser repeaterDefinitionParser) throws ConfigurationException 181 { 182 RepeaterDefinition repeaterDefinition = repeaterDefinitionParser.parse(_manager, pluginName, catalog, repeaterConfiguration, model, parent); 183 184 if (repeaterDefinition != null) 185 { 186 ModelViewItemGroup viewItemGroup = new ModelViewItemGroup(); 187 viewItemGroup.setDefinition(repeaterDefinition); 188 189 _parseChildren(repeaterConfiguration, viewItemGroup, repeaterDefinition, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 190 191 return viewItemGroup; 192 } 193 194 return null; 195 } 196 197 /** 198 * Parses children of a view item container 199 * @param containerConfiguration the item container configuration 200 * @param viewItemContainer the item container 201 * @param modelParent The last model item container to use as parent for next definitions 202 * @param pluginName the plugin name 203 * @param catalog the catalog 204 * @param view the view 205 * @param modelItems the map of model items 206 * @param model the model 207 * @param elementDefinitionParser the element definition parser 208 * @param repeaterDefinitionParser the repeater definition parser 209 * @throws ConfigurationException if an error occurs 210 */ 211 protected void _parseChildren(Configuration containerConfiguration, ViewItemContainer viewItemContainer, ModelItemGroup modelParent, String pluginName, String catalog, View view, Map<String, ModelItem> modelItems, Model model, ElementDefinitionParser elementDefinitionParser, RepeaterDefinitionParser repeaterDefinitionParser) throws ConfigurationException 212 { 213 Configuration[] children = containerConfiguration.getChildren(); 214 for (Configuration child : children) 215 { 216 ViewItem viewItem = null; 217 switch (child.getName()) 218 { 219 case "fieldset": 220 viewItem = _parseSimpleViewItemGroup(child, modelParent, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 221 ((ViewItemGroup) viewItem).setRole(ViewItemGroup.FIELDSET_ROLE); 222 break; 223 case "parameter": 224 viewItem = parseParameter(child, modelParent, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 225 break; 226 case "repeater": 227 viewItem = parseRepeater(child, modelParent, pluginName, catalog, view, modelItems, model, elementDefinitionParser, repeaterDefinitionParser); 228 break; 229 case "group": 230 throw new ConfigurationException("This parameters configuration should not have subgroups", child); 231 default: 232 break; 233 } 234 235 if (viewItem != null) 236 { 237 viewItemContainer.addViewItem(viewItem); 238 if (viewItem instanceof ModelViewItem && modelParent == null) 239 { 240 ModelItem definition = ((ModelViewItem) viewItem).getDefinition(); 241 String name = definition.getName(); 242 if (modelItems.containsKey(name)) 243 { 244 getLogger().warn("Parameter with name '{}' is defined twice in the configuration. It will be ignored", name); 245 } 246 else 247 { 248 modelItems.put(name, definition); 249 } 250 } 251 } 252 } 253 } 254 255 /** 256 * Parse an i18n text. 257 * @param config the configuration to use. 258 * @param name the child name. 259 * @param pluginName the plugin name 260 * @param catalog the catalog 261 * @return the i18n text. 262 */ 263 protected I18nizableText _parseI18nizableText(Configuration config, String name, String pluginName, String catalog) 264 { 265 String catalogName = StringUtils.isNotBlank(catalog) ? catalog : "plugin." + pluginName; 266 return I18nizableText.parseI18nizableText(config.getChild(name), catalogName, ""); 267 } 268 269 /** 270 * The view and parameters object 271 */ 272 public static class ViewAndParameters 273 { 274 View _view; 275 Map<String, ModelItem> _modelItems; 276 277 ViewAndParameters(View view, Map<String, ModelItem> modelItems) 278 { 279 this._view = view; 280 this._modelItems = modelItems; 281 } 282 283 /** 284 * Get the view 285 * @return the view 286 */ 287 public View getView() 288 { 289 return this._view; 290 } 291 292 /** 293 * Get the map of model items 294 * @return the map of model items 295 */ 296 public Map<String, ModelItem> getParameters() 297 { 298 return this._modelItems; 299 } 300 } 301}