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