001/*
002 *  Copyright 2021 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.plugins.forms.question.types;
017
018import java.util.List;
019import java.util.Map;
020
021import org.ametys.plugins.forms.helper.FormElementDefinitionHelper;
022import org.ametys.plugins.forms.question.validators.NumberIntervalFormValidator;
023import org.ametys.plugins.forms.repository.FormQuestion;
024import org.ametys.runtime.config.DisableCondition;
025import org.ametys.runtime.config.DisableCondition.OPERATOR;
026import org.ametys.runtime.config.DisableConditions;
027import org.ametys.runtime.i18n.I18nizableText;
028import org.ametys.runtime.model.ElementDefinition;
029import org.ametys.runtime.model.ModelItem;
030import org.ametys.runtime.model.SimpleViewItemGroup;
031import org.ametys.runtime.model.StaticEnumerator;
032import org.ametys.runtime.model.ViewElement;
033import org.ametys.runtime.model.type.ModelItemTypeConstants;
034
035/**
036 * Class for creating number question type
037 */
038public class NumberQuestionType extends AbstractFormQuestionType
039{
040    /** Constant for min attribute */
041    public static final String ATTRIBUTE_MIN_DOUBLE = "min-double";
042    
043    /** Constant for max attribute */
044    public static final String ATTRIBUTE_MAX_DOUBLE = "max-double";
045    
046    /** Constant for min attribute */
047    public static final String ATTRIBUTE_MIN_INT = "min-int";
048    
049    /** Constant for max attribute */
050    public static final String ATTRIBUTE_MAX_INT = "max-int";
051    
052    /** Constant for number type attribute */
053    public static final String ATTRIBUTE_NUMBER_TYPE = "number-type";
054    
055    /** Name of double numberTypeStaticEnumerator entry  */
056    public static final String DOUBLE_NUMBER_VALUE = "double";
057    
058    /** Name of integer numberTypeStaticEnumerator entry  */
059    public static final String INTEGER_NUMBER_VALUE = "int";
060    
061    /** Constant for default title */
062    public static final String DEFAULT_TITLE = "PLUGIN_FORMS_QUESTION_DEFAULT_TITLE_NUMBER";
063    
064    @Override
065    protected SimpleViewItemGroup _getAdvancedTab()
066    {
067        SimpleViewItemGroup advancedFieldset = super._getAdvancedTab();
068        
069        ViewElement numberType = new ViewElement();
070        numberType.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_NUMBER_TYPE));
071        advancedFieldset.addViewItem(numberType);
072        
073        ViewElement min = new ViewElement();
074        min.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_MIN_DOUBLE));
075        advancedFieldset.addViewItem(min);
076        
077        ViewElement max = new ViewElement();
078        max.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_MAX_DOUBLE));
079        advancedFieldset.addViewItem(max);
080        
081        ViewElement minInt = new ViewElement();
082        minInt.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_MIN_INT));
083        advancedFieldset.addViewItem(minInt);
084        
085        ViewElement maxInt = new ViewElement();
086        maxInt.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_MAX_INT));
087        advancedFieldset.addViewItem(maxInt);
088        
089        return advancedFieldset;
090    }
091
092    @Override
093    protected List<ModelItem> _getModelItems()
094    {
095        List<ModelItem> modelItems = super._getModelItems();
096        
097        // DOUBLE Conditions
098        DisableConditions doubleDisableConditions = new DisableConditions();
099        DisableCondition conditionDouble = new DisableCondition(ATTRIBUTE_NUMBER_TYPE, OPERATOR.NEQ, DOUBLE_NUMBER_VALUE);
100        doubleDisableConditions.getConditions().add(conditionDouble);
101        //MIN
102        ElementDefinition minDouble = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_MIN_DOUBLE, ModelItemTypeConstants.DOUBLE_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MIN", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MIN_DESC", null);
103        minDouble.setDisableConditions(doubleDisableConditions);
104        modelItems.add(minDouble);
105        
106        //MAX
107        ElementDefinition maxDouble = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_MAX_DOUBLE, ModelItemTypeConstants.DOUBLE_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MAX", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MAX_DESC", null);
108        maxDouble.setDisableConditions(doubleDisableConditions);
109        modelItems.add(maxDouble);
110        
111        // INTEGER Conditions
112        DisableConditions integerDisableConditions = new DisableConditions();
113        DisableCondition conditionInteger = new DisableCondition(ATTRIBUTE_NUMBER_TYPE, OPERATOR.NEQ, INTEGER_NUMBER_VALUE);
114        integerDisableConditions.getConditions().add(conditionInteger);
115        //MIN
116        ElementDefinition minInt = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_MIN_INT, ModelItemTypeConstants.LONG_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MIN", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MIN_DESC", null);
117        minInt.setDisableConditions(integerDisableConditions);
118        modelItems.add(minInt);
119        
120        //MAX
121        ElementDefinition maxInt = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_MAX_INT, ModelItemTypeConstants.LONG_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MAX", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_MAX_DESC", null);
122        maxInt.setDisableConditions(integerDisableConditions);
123        modelItems.add(maxInt);
124        
125        //NUMBER_TYPE
126        ElementDefinition<String> numberType = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_NUMBER_TYPE, ModelItemTypeConstants.STRING_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_NUMBER_TYPE", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_NUMBER_TYPE_DESC", null);
127
128        StaticEnumerator<String> numberTypeStaticEnumerator = new StaticEnumerator<>();
129        numberTypeStaticEnumerator.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_TYPE_DOUBLE"), DOUBLE_NUMBER_VALUE);
130        numberTypeStaticEnumerator.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_TYPE_INT"), INTEGER_NUMBER_VALUE);
131        numberType.setEnumerator(numberTypeStaticEnumerator);
132        numberType.setDefaultValue(INTEGER_NUMBER_VALUE);
133        modelItems.add(numberType);
134        
135        return modelItems;
136    }
137    
138    public String getStorageType(FormQuestion question)
139    {
140        String type = question.getValue(ATTRIBUTE_NUMBER_TYPE);
141        return type.equals(DOUBLE_NUMBER_VALUE) ? ModelItemTypeConstants.DOUBLE_TYPE_ID : ModelItemTypeConstants.LONG_TYPE_ID;
142    }
143    
144    @Override
145    protected ModelItem _getEntryModelItem(FormQuestion question)
146    {
147        ModelItem item = super._getEntryModelItem(question);
148        if (DOUBLE_NUMBER_VALUE.equals(question.getValue(ATTRIBUTE_NUMBER_TYPE)))
149        {
150            ((ElementDefinition) item).setValidator(new NumberIntervalFormValidator(null, isMandatory(question), question.getValue(ATTRIBUTE_MIN_DOUBLE), question.getValue(ATTRIBUTE_MAX_DOUBLE)));
151        }
152        else
153        {
154            ((ElementDefinition) item).setValidator(new NumberIntervalFormValidator(null, isMandatory(question), question.getValue(ATTRIBUTE_MIN_INT), question.getValue(ATTRIBUTE_MAX_INT)));
155        }
156        return item;
157    }
158    
159    @Override
160    public void validateQuestionValues(Map<String, Object> values, Map<String, I18nizableText> errors)
161    {
162        super.validateQuestionValues(values, errors);
163        
164        String format = (String) values.get(ATTRIBUTE_NUMBER_TYPE);
165        switch (format)
166        {
167            case DOUBLE_NUMBER_VALUE:
168                Number minDouble = (Number) values.getOrDefault(ATTRIBUTE_MIN_DOUBLE, null);
169                Number maxDouble = (Number) values.getOrDefault(ATTRIBUTE_MAX_DOUBLE, null);
170                if (minDouble != null && maxDouble != null && minDouble.doubleValue() > maxDouble.doubleValue())
171                {
172                    errors.put(ATTRIBUTE_MIN_DOUBLE, new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_GAP_ERROR"));
173                    errors.put(ATTRIBUTE_MAX_DOUBLE, new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_GAP_ERROR"));
174                }
175                break;
176            
177            case INTEGER_NUMBER_VALUE:
178                Number min = (Number) values.getOrDefault(ATTRIBUTE_MIN_INT, null);
179                Number max = (Number) values.getOrDefault(ATTRIBUTE_MAX_INT, null);
180                if (min != null && max != null && min.longValue() > max.longValue())
181                {
182                    errors.put(ATTRIBUTE_MIN_INT, new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_GAP_ERROR"));
183                    errors.put(ATTRIBUTE_MAX_INT, new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_NUMBER_GAP_ERROR"));
184                }
185                break;
186            
187            default:
188                getLogger().error("Number format " + format + " is not supported");
189                break;
190        }
191    }
192    
193    public I18nizableText getDefaultTitle()
194    {
195        return new I18nizableText("plugin.forms", DEFAULT_TITLE);
196    }
197    
198    @Override
199    public List<String> getFieldToDisableIfFormPublished(FormQuestion question)
200    {
201        List<String> fieldNames =  super.getFieldToDisableIfFormPublished(question);
202        fieldNames.add(ATTRIBUTE_NUMBER_TYPE);
203        return fieldNames;
204    }
205}