001/*
002 *  Copyright 2022 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.helper;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.stream.Collectors;
023
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028
029import org.ametys.core.ui.Callable;
030import org.ametys.plugins.forms.question.FormQuestionType;
031import org.ametys.plugins.forms.question.sources.ChoiceSourceType;
032import org.ametys.plugins.forms.question.types.CheckBoxQuestionType;
033import org.ametys.plugins.forms.question.types.ChoicesListQuestionType;
034import org.ametys.plugins.forms.repository.Form;
035import org.ametys.plugins.forms.repository.FormQuestion;
036import org.ametys.plugins.forms.repository.type.Rule.QuestionRuleType;
037import org.ametys.plugins.repository.AmetysObjectResolver;
038import org.ametys.runtime.i18n.I18nizableText;
039
040/**
041 * Helper for getting rules properties
042 */
043public class QuestionRuleHelper implements Serviceable, Component
044{
045    /** The Ametys object resolver */
046    protected AmetysObjectResolver _resolver;
047    
048    public void service(ServiceManager manager) throws ServiceException
049    {
050        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
051    }
052    
053    /**
054     * Get all choices list and booleans questions as source for the rule
055     * @param formId id of the current form
056     * @param questionId id of the current question
057     * @return a map containing the list of questions
058     */
059    @Callable
060    public Map<String, Object> getSourceQuestions(String formId, String questionId)
061    {
062        Map<String, Object> results = new HashMap<>();
063        Form form = _resolver.resolveById(formId);
064        List<FormQuestion> questions = form.getQuestions()
065            .stream()
066            .filter(question -> this._isChoiceListWithNoToManyOptions(question) || question.getType() instanceof CheckBoxQuestionType)
067            .filter(question -> !question.getId().equals(questionId))
068            .collect(Collectors.toList());
069        List<Object> sources = new ArrayList<>();
070        for (FormQuestion question : questions)
071        {
072            Map<String, String> properties = new HashMap<>();
073            properties.put("label", question.getTitle());
074            properties.put("id", question.getId());
075            sources.add(properties);
076        }
077        results.put("data", sources);
078        
079        return results;
080    }
081    
082    private boolean _isChoiceListWithNoToManyOptions(FormQuestion question)
083    {
084        FormQuestionType type = question.getType();
085        if (type instanceof ChoicesListQuestionType cLType)
086        {
087            ChoiceSourceType sourceType = cLType.getSourceType(question);
088            return !sourceType.remoteData();
089        }
090        
091        return false;
092    }
093    
094    /**
095     * Get all the available options for the selected question
096     * @param questionId id of the selected question
097     * @return a map containing the list of all the options as map (label for display and unique value)
098     */
099    @Callable
100    public Map<String, Object> getSourceOptions(String questionId)
101    {
102        Map<String, Object> results = new HashMap<>();
103        FormQuestion formQuestion = _resolver.resolveById(questionId);
104        List<Object> options = new ArrayList<>();
105        if (formQuestion.getType() instanceof ChoicesListQuestionType type && !type.getSourceType(formQuestion).remoteData())
106        {
107            Map<String, I18nizableText> choices = type.getOptions(formQuestion);
108            for (String optionValue : choices.keySet())
109            {
110                Map<String, Object> choicesToJson = new HashMap<>();
111                choicesToJson.put("label", choices.get(optionValue));
112                choicesToJson.put("value", optionValue);
113                options.add(choicesToJson);
114            }
115            if (type.hasOtherOption(formQuestion))
116            {
117                Map<String, Object> choicesToJson = new HashMap<>();
118                choicesToJson.put("label", new I18nizableText("plugin.forms", "PLUGINS_FORMS_DISPLAY_OTHER_OPTION_COMBOBOX"));
119                choicesToJson.put("value", ChoicesListQuestionType.OTHER_OPTION_VALUE);
120                options.add(choicesToJson);
121            }
122        }
123        else
124        {
125            options.add(Map.of(
126                    "label", new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTION_RULES_OPTION_CHECKED"),
127                    "value", "true"
128                    ));
129            
130            options.add(Map.of(
131                    "label", new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTION_RULES_OPTION_UNCHECKED"),
132                    "value", "false"
133                    ));
134        }
135        results.put("data", options);
136        return results;
137    }
138    
139    /**
140     * Get the actions available to apply to this question 
141     * @return a list of actions (currently hide or show)
142     */
143    @Callable
144    public Map<String, Object> getRuleActions()
145    {
146        Map<String, Object> results = new HashMap<>();
147        
148        List<Object> actions = new ArrayList<>();
149        
150        actions.add(Map.of(
151            "label", QuestionRuleType.HIDE.getLabel(),
152            "value", QuestionRuleType.HIDE.name()
153        ));
154        
155        actions.add(Map.of(
156            "label", QuestionRuleType.SHOW.getLabel(),
157            "value", QuestionRuleType.SHOW.name()
158        ));
159        
160        results.put("data", actions);
161        return results;
162    }
163}