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}