001/* 002 * Copyright 2023 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.actions; 017 018import java.util.List; 019import java.util.Map; 020import java.util.Optional; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.acting.ServiceableAction; 025import org.apache.cocoon.environment.Request; 026 027import org.ametys.core.right.RightManager; 028import org.ametys.plugins.forms.dao.FormDAO; 029import org.ametys.plugins.forms.dao.FormEntryDAO; 030import org.ametys.plugins.forms.dao.FormQuestionDAO; 031import org.ametys.plugins.forms.dao.FormQuestionDAO.FormEntryValues; 032import org.ametys.plugins.forms.question.FormQuestionType; 033import org.ametys.plugins.forms.question.sources.ChoiceSourceType; 034import org.ametys.plugins.forms.question.types.ChoicesListQuestionType; 035import org.ametys.plugins.forms.question.types.ComputedQuestionType; 036import org.ametys.plugins.forms.repository.Form; 037import org.ametys.plugins.forms.repository.FormEntry; 038import org.ametys.plugins.forms.repository.FormQuestion; 039import org.ametys.plugins.repository.AmetysObjectResolver; 040import org.ametys.runtime.model.View; 041import org.ametys.runtime.model.ViewItem; 042import org.ametys.web.FOAmetysObjectCreationHelper; 043 044/** 045 * Abstract action to process form entry inputs 046 */ 047public abstract class AbstractProcessFormAction extends ServiceableAction 048{ 049 /** The ametys object resolver */ 050 protected AmetysObjectResolver _resolver; 051 052 /** The FO ametys object creation helper */ 053 protected FOAmetysObjectCreationHelper _foAmetysObjectCreationHelper; 054 055 /** The form DAO */ 056 protected FormDAO _formDAO; 057 058 /** The form entry DAO */ 059 protected FormEntryDAO _entryDAO; 060 061 /** The form question DAO */ 062 protected FormQuestionDAO _formQuestionDAO; 063 064 /** The right manager */ 065 protected RightManager _rightManager; 066 067 @Override 068 public void service(ServiceManager smanager) throws ServiceException 069 { 070 super.service(smanager); 071 _foAmetysObjectCreationHelper = (FOAmetysObjectCreationHelper) smanager.lookup(FOAmetysObjectCreationHelper.ROLE); 072 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 073 _formDAO = (FormDAO) smanager.lookup(FormDAO.ROLE); 074 _entryDAO = (FormEntryDAO) smanager.lookup(FormEntryDAO.ROLE); 075 _formQuestionDAO = (FormQuestionDAO) smanager.lookup(FormQuestionDAO.ROLE); 076 _rightManager = (RightManager) smanager.lookup(RightManager.ROLE); 077 } 078 079 /** 080 * Remove empty value for choice list because empty value is an other value 081 * @param form the form 082 * @param formInputValues the form inputs to change 083 */ 084 protected void _adaptFormValuesForChoiceList(Form form, Map<String, Object> formInputValues) 085 { 086 List<FormQuestion> choiceListQuestions = form.getQuestions() 087 .stream() 088 .filter(q -> q.getType() instanceof ChoicesListQuestionType) 089 .toList(); 090 091 for (FormQuestion question : choiceListQuestions) 092 { 093 ChoicesListQuestionType type = (ChoicesListQuestionType) question.getType(); 094 ChoiceSourceType sourceType = type.getSourceType(question); 095 096 String nameForForm = question.getNameForForm(); 097 if (formInputValues.containsKey(nameForForm)) 098 { 099 Object object = formInputValues.get(nameForForm); 100 Object newValue = sourceType.removeEmptyOrOtherValue(object); 101 if (newValue == null) 102 { 103 formInputValues.remove(nameForForm); 104 } 105 else 106 { 107 formInputValues.put(nameForForm, newValue); 108 } 109 110 } 111 } 112 } 113 114 /** 115 * Get a view without elements hidden by a rule 116 * @param request the request 117 * @param form The current form 118 * @param entryView The entry view with possibly unwanted viewItems 119 * @param entryValues The entry values 120 * @param currentStepId current step of the entry. Can be empty if the form has no workflow 121 * @return a view with filtered items 122 */ 123 protected View _getRuleFilteredEntryView(Request request, Form form, View entryView, FormEntryValues entryValues, Optional<Long> currentStepId) 124 { 125 View filteredEntryView = new View(); 126 for (FormQuestion target : _getRuleFilteredQuestions(request, form, entryValues, currentStepId)) 127 { 128 ViewItem viewItem = entryView.getViewItem(target.getNameForForm()); 129 filteredEntryView.addViewItem(viewItem); 130 _manageOtherOption(entryView, filteredEntryView, target); 131 } 132 return filteredEntryView; 133 } 134 135 /** 136 * Get the list of active question depending of the form rules 137 * @param request the request 138 * @param form the form 139 * @param entryValues the entry values to compute rules 140 * @param currentStepId the current step id. Can be empty if the form has no workflow 141 * @return the list of active question depending of the form rules 142 */ 143 protected abstract List<FormQuestion> _getRuleFilteredQuestions(Request request, Form form, FormEntryValues entryValues, Optional<Long> currentStepId); 144 145 private void _manageOtherOption(View entryView, View filteredEntryView, FormQuestion target) 146 { 147 if (target.getType() instanceof ChoicesListQuestionType type && type.hasOtherOption(target)) 148 { 149 ViewItem viewOtherItem = entryView.getViewItem(ChoicesListQuestionType.OTHER_PREFIX_DATA_NAME + target.getNameForForm()); 150 filteredEntryView.addViewItem(viewOtherItem); 151 } 152 } 153 154 /** 155 * Handle computed values 156 * @param questions the form questions 157 * @param entry the entry 158 * @param forEdition <code>true</code> to handle edition 159 */ 160 protected void _handleComputedValues(List<FormQuestion> questions, FormEntry entry, boolean forEdition) 161 { 162 for (FormQuestion question : questions) 163 { 164 FormQuestionType questionType = question.getType(); 165 if (questionType instanceof ComputedQuestionType type) 166 { 167 if (!forEdition || type.getComputingType(question).canEdit()) 168 { 169 Object computedValue = type.getComputingType(question).getComputedValue(question, entry); 170 if (computedValue != null) 171 { 172 entry.setValue(question.getNameForForm(), computedValue); 173 } 174 } 175 } 176 } 177 } 178}