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.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.cocoon.ProcessingException;
024
025import org.ametys.runtime.config.DisableCondition;
026import org.ametys.runtime.config.DisableConditions;
027import org.ametys.runtime.i18n.I18nizableText;
028import org.ametys.runtime.model.type.ElementType;
029import org.ametys.runtime.model.type.ModelItemType;
030import org.ametys.runtime.parameter.Validator;
031
032/**
033 * The definition of a single model item (parameter, attribute)
034 * @param <T> Type of the element value
035 */
036public class ElementDefinition<T> extends AbstractModelItem
037{
038    private String _pluginName;
039    private ElementType<T> _type;
040    private String _widget;
041    private Map<String, I18nizableText> _widgetParams;
042    private Enumerator<T> _enumerator;
043    private Validator _validator;
044    private T _defaultValue;
045    private boolean _isMultiple;
046    private DisableConditions _disableConditions;
047    
048    /**
049     * Retrieves the name of the plugin declaring this element.
050     * @return the plugin name.
051     */
052    public String getPluginName()
053    {
054        return _pluginName;
055    }
056
057    /**
058     * Set the name of the plugin declaring this element.
059     * @param pluginName the plugin name.
060     */
061    public void setPluginName(String pluginName)
062    {
063        _pluginName = pluginName;
064    }
065
066    @Override
067    public ElementType<T> getType()
068    {
069        return _type;
070    }
071
072    @SuppressWarnings("unchecked")
073    public void setType(ModelItemType type)
074    {
075        if (type instanceof ElementType)
076        {
077            _type = (ElementType<T>) type;
078        }
079        else
080        {
081            throw new IllegalArgumentException("Unable to set the type '" + type.getClass() + "' on the element type '" + getName() + "'");
082        }
083    }
084
085    /**
086     * Retrieves the widget to use for rendering.
087     * @return the widget or <code>null</code> if none is defined.
088     */
089    public String getWidget()
090    {
091        return _widget;
092    }
093
094    /**
095     * Set the widget.
096     * @param widget the widget.
097     */
098    public void setWidget(String widget)
099    {
100        _widget = widget;
101    }
102    
103    /**
104     * Get the widget's parameters
105     * @return the widget's parameters
106     */
107    public Map<String, I18nizableText> getWidgetParameters()
108    {
109        return _widgetParams;
110    }
111    
112    /**
113     * Set the widget's parameters
114     * @param params the parameters to set
115     */
116    public void setWidgetParameters (Map<String, I18nizableText> params)
117    {
118        _widgetParams = params;
119    }
120    
121    /**
122     * Retrieves the enumerator.
123     * @return the enumerator or <code>null</code> if none is defined.
124     */
125    public Enumerator<T> getEnumerator()
126    {
127        return _enumerator;
128    }
129
130    /**
131     * Set the enumerator.
132     * @param enumerator the enumerator.
133     */
134    public void setEnumerator(Enumerator<T> enumerator)
135    {
136        _enumerator = enumerator;
137    }
138
139    /**
140     * Retrieves the validator.
141     * @return the validator or <code>null</code> if none is defined.
142     */
143    public Validator getValidator()
144    {
145        return _validator;
146    }
147
148    /**
149     * Set the validator.
150     * @param validator the validator.
151     */
152    public void setValidator(Validator validator)
153    {
154        _validator = validator;
155    }
156
157    /**
158     * Retrieves the default value.
159     * @return the default value or <code>null</code> if none is defined.
160     */
161    public T getDefaultValue()
162    {
163        return _defaultValue;
164    }
165
166    /**
167     * Set the default value.
168     * @param defaultValue the default value.
169     */
170    public void setDefaultValue(T defaultValue)
171    {
172        _defaultValue = defaultValue;
173    }
174
175    /**
176     * Test if the element is multiple.
177     * @return <code>true</code> if the metadata is multiple.
178     */
179    public boolean isMultiple()
180    {
181        return _isMultiple;
182    }
183    
184    /**
185     * Set the element multiple status.
186     * @param isMultiple the element multiple status.
187     */
188    public void setMultiple(boolean isMultiple)
189    {
190        _isMultiple = isMultiple;
191    }
192    
193    /**
194     * Retrieves the disable condition.
195     * @return the disable condition or <code>null</code> if none is defined.
196     */
197    public DisableConditions getDisableConditions()
198    {
199        return _disableConditions;
200    }
201
202    /**
203     * Sets the disable condition.
204     * @param disableConditions the disable condition.
205     */
206    public void setDisableConditions(DisableConditions disableConditions)
207    {
208        _disableConditions = disableConditions;
209    }
210
211    @Override
212    public Map<String, Object> toJSON() throws ProcessingException
213    {
214        Map<String, Object> result = super.toJSON();
215        
216        result.put("plugin", getPluginName());
217        result.put("multiple", isMultiple());
218        
219        if (getType() != null)
220        {
221            result.put("type", getType().getId());
222            result.put("default-value", getType().valueToJSONForClient(getDefaultValue()));
223        }
224        
225        
226        if (getValidator() != null)
227        {
228            result.put("validation", getValidator().getConfiguration());
229        }
230        
231        if (getEnumerator() != null)
232        {
233            List<Map<String, Object>> enumeration = new ArrayList<>();
234            
235            try
236            {
237                Map<T, I18nizableText> entries = getEnumerator().getTypedEntries();
238                for (Map.Entry<T, I18nizableText> entry : entries.entrySet())
239                {
240                    Map<String, Object> option = new HashMap<>();
241                    option.put("value", getType().valueToJSONForClient(entry.getKey()));
242                    option.put("label", entry.getValue());
243                    enumeration.add(option);
244                }
245            }
246            catch (Exception e)
247            {
248                throw new ProcessingException("Unable to enumerate entries with enumerator: " + getEnumerator(), e);
249            }
250            
251            result.put("enumeration", enumeration);
252            result.put("enumerationConfig", getEnumerator().getConfiguration());
253        }
254        
255        result.put("widget", getWidget());
256        
257        Map<String, I18nizableText> widgetParameters = getWidgetParameters();
258        if (widgetParameters != null && !widgetParameters.isEmpty())
259        {
260            result.put("widget-params", widgetParameters);
261        }
262        
263        if (getDisableConditions() != null)
264        {
265            result.put("disableCondition", _disableConditionstoJSON(getDisableConditions()));
266        }
267        
268        return result;
269    }
270    
271    /**
272     * Converts the definition's disable conditions in a JSON map
273     * @param disableConditions the disable conditions to convert
274     * @return The definition's disable conditions as a JSON map
275     */
276    private Map<String, Object> _disableConditionstoJSON(DisableConditions disableConditions)
277    {
278        Map<String, Object> map = new HashMap<>();
279        
280        // Handle simple conditions
281        List<Map<String, String>> disableConditionList = new ArrayList<>();
282        map.put("condition", disableConditionList);
283        for (DisableCondition disableCondition : disableConditions.getConditions())
284        {
285            Map<String, String> disableConditionAsMap = _disableConditiontoJSON(disableCondition);
286            disableConditionList.add(disableConditionAsMap);
287        }
288
289        // Handle nested conditions
290        List<Map<String, Object>> disableConditionsList = new ArrayList<>();
291        map.put("conditions", disableConditionsList);
292        for (DisableConditions subDisableConditions : disableConditions.getSubConditions())
293        {
294            Map<String, Object> disableConditionsAsMap = _disableConditionstoJSON(subDisableConditions);
295            disableConditionsList.add(disableConditionsAsMap);
296        }
297        
298        // Handle type
299        map.put("type", disableConditions.getAssociationType().toString().toLowerCase());
300        
301        return map; 
302    }
303
304    private static Map<String, String> _disableConditiontoJSON(DisableCondition disableCondition)
305    {
306        Map<String, String> map = new HashMap<>();
307        map.put("id", disableCondition.getId());
308        map.put("operator", disableCondition.getOperator().toString().toLowerCase());
309        map.put("value", disableCondition.getValue());
310        return map;
311    }
312}