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.generators; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Optional; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.xml.AttributesImpl; 029import org.apache.cocoon.xml.XMLUtils; 030import org.apache.commons.lang3.StringUtils; 031import org.xml.sax.SAXException; 032 033import org.ametys.cms.workflow.AmetysObjectCheckRightsCondition; 034import org.ametys.core.user.User; 035import org.ametys.core.user.UserIdentity; 036import org.ametys.core.user.UserManager; 037import org.ametys.plugins.forms.data.Answer; 038import org.ametys.plugins.forms.helper.FormAdminDashboardHelper; 039import org.ametys.plugins.forms.helper.FormMailHelper; 040import org.ametys.plugins.forms.repository.Form; 041import org.ametys.plugins.forms.repository.FormEntry; 042import org.ametys.plugins.forms.repository.FormQuestion; 043import org.ametys.runtime.i18n.I18nizableText; 044import org.ametys.web.WebHelper; 045 046import com.opensymphony.workflow.Workflow; 047import com.opensymphony.workflow.loader.ActionDescriptor; 048import com.opensymphony.workflow.loader.WorkflowDescriptor; 049 050/** 051 * This class generates all the forms process information for current user 052 */ 053public class FormAdminDashboardGenerator extends FormDashboardGenerator 054{ 055 /** The default number of entries by page */ 056 private static int __DEFAULT_NB_ENTRIES_BY_PAGE = 10; 057 058 /** The user manager */ 059 protected UserManager _userManager; 060 061 /** The form mail helper */ 062 protected FormMailHelper _formMailHelper; 063 064 /** The form admin dashboard helper */ 065 protected FormAdminDashboardHelper _formAdminDashboardHelper; 066 067 @Override 068 public void service(ServiceManager smanager) throws ServiceException 069 { 070 super.service(smanager); 071 _userManager = (UserManager) smanager.lookup(UserManager.ROLE); 072 _formMailHelper = (FormMailHelper) smanager.lookup(FormMailHelper.ROLE); 073 _formAdminDashboardHelper = (FormAdminDashboardHelper) smanager.lookup(FormAdminDashboardHelper.ROLE); 074 } 075 076 @Override 077 protected void _saxFormDashboardData(UserIdentity user) throws SAXException 078 { 079 XMLUtils.startElement(contentHandler, "dashboard"); 080 081 Request request = ObjectModelHelper.getRequest(objectModel); 082 String siteName = WebHelper.getSiteName(request); 083 084 String formId = request.getParameter("formId"); 085 // No need to sax the forms if a form is send in the request 086 if (StringUtils.isBlank(formId)) 087 { 088 List<Form> forms = _formAdminDashboardHelper.getFormToAdmin(siteName, user); 089 // Sax the forms for user selection 090 _saxForms(forms); 091 } 092 else 093 { 094 // Sax form entries 095 _saxFormEntries(request, formId, user); 096 } 097 098 099 XMLUtils.endElement(contentHandler, "dashboard"); 100 } 101 102 /** 103 * Sax the forms 104 * @param forms the list of form 105 * @throws SAXException if a saxing error occurred 106 */ 107 protected void _saxForms(List<Form> forms) throws SAXException 108 { 109 XMLUtils.startElement(contentHandler, "forms"); 110 for (Form form : forms) 111 { 112 AttributesImpl attrs = new AttributesImpl(); 113 attrs.addCDATAAttribute("id", form.getId()); 114 XMLUtils.startElement(contentHandler, "form", attrs); 115 116 XMLUtils.createElement(contentHandler, "title", form.getTitle()); 117 118 String description = form.getDescription(); 119 if (description != null) 120 { 121 XMLUtils.createElement(contentHandler, "description", description); 122 } 123 124 XMLUtils.endElement(contentHandler, "form"); 125 } 126 XMLUtils.endElement(contentHandler, "forms"); 127 } 128 129 /** 130 * Get available form entries for given page 131 * @param formId the form id 132 * @param page the page 133 * @param nbEntriesByPage the number of entries by page 134 * @return the entries record 135 */ 136 protected EntriesRecord _getAvailableFormEntries(String formId, int page, int nbEntriesByPage) 137 { 138 List<FormEntry> availableEntries = new ArrayList<>(); 139 140 Form form = _resolver.resolveById(formId); 141 List<FormEntry> entries = form.getEntries() 142 .stream() 143 .sorted((e1, e2) -> Long.compare(e1.getEntryId(), e2.getEntryId())) 144 .toList(); 145 146 int activeEntriesSize = entries.size(); 147 int nbAnswer = 0; 148 int position = 0; 149 int lastEntryIndex = page * nbEntriesByPage; 150 boolean hasNextPage = false; 151 while (nbAnswer <= lastEntryIndex && position < activeEntriesSize) 152 { 153 FormEntry entry = entries.get(position); 154 if (_formAdminDashboardHelper.hasAvailableActions(entry)) 155 { 156 if (nbAnswer == lastEntryIndex) 157 { 158 hasNextPage = true; 159 } 160 else 161 { 162 availableEntries.add(entry); 163 } 164 nbAnswer++; 165 } 166 position++; 167 } 168 169 return new EntriesRecord(availableEntries, hasNextPage); 170 } 171 172 /** 173 * Sax the form entries 174 * @param request the request 175 * @param formId the form id 176 * @param user the current user 177 * @throws SAXException if a saxing error occurred 178 */ 179 protected void _saxFormEntries(Request request, String formId, UserIdentity user) throws SAXException 180 { 181 Form form = _resolver.resolveById(formId); 182 183 int nbAnswerByPage = StringUtils.isNotBlank(request.getParameter("nbEntriesByPage")) ? Integer.parseInt(request.getParameter("nbEntriesByPage")) : __DEFAULT_NB_ENTRIES_BY_PAGE; 184 int page = request.getParameter("page") != null ? Integer.parseInt(request.getParameter("page")) : 1; 185 186 EntriesRecord availableFormEntries = _getAvailableFormEntries(formId, page, nbAnswerByPage); 187 List<FormEntry> entries = availableFormEntries.entries(); 188 189 // Recalculate the page 190 int size = entries.size(); 191 int mod = size % nbAnswerByPage; 192 page = mod == 0 && size != 0 ? (size / nbAnswerByPage) : (size / nbAnswerByPage) + 1; 193 List<FormEntry> entriesToSax = entries.subList((page - 1) * nbAnswerByPage, Math.min(page * nbAnswerByPage, size)); 194 195 // Sax entries 196 AttributesImpl attrs = new AttributesImpl(); 197 attrs.addCDATAAttribute("formId", formId); 198 attrs.addCDATAAttribute("formTitle", form.getTitle()); 199 attrs.addCDATAAttribute("page", String.valueOf(page)); 200 attrs.addCDATAAttribute("hasNextPage", String.valueOf(availableFormEntries.hasNextEntries())); 201 XMLUtils.startElement(contentHandler, "answers", attrs); 202 try 203 { 204 for (FormEntry entry : entriesToSax) 205 { 206 _saxAnswer(_formEntry2Answer(entry), user); 207 } 208 } 209 catch (Exception e) 210 { 211 getLogger().error("An error occurred saxing answers", e); 212 } 213 XMLUtils.endElement(contentHandler, "answers"); 214 } 215 216 @Override 217 protected void _saxWorkflowInformations(Answer answer, UserIdentity user) throws Exception 218 { 219 super._saxWorkflowInformations(answer, user); 220 221 Workflow workflow = _getWorkflow(answer); 222 223 FormEntry formEntry = _resolver.resolveById(answer.getId()); 224 _saxMailUsersInformations(formEntry, user); 225 226 Map<String, Object> inputs = new HashMap<>(); 227 inputs.put(AmetysObjectCheckRightsCondition.AMETYS_OBJECT_KEY, formEntry); 228 229 WorkflowDescriptor workflowDescriptor = _workflowHelper.getWorkflowDescriptor(answer.getWorkflowName()); 230 int[] availableActions = workflow.getAvailableActions(answer.getWorkflowId(), inputs); 231 for (int actionId : availableActions) 232 { 233 ActionDescriptor action = workflowDescriptor.getAction(actionId); 234 235 AttributesImpl attrs = new AttributesImpl(); 236 attrs.addCDATAAttribute("id", String.valueOf(actionId)); 237 238 Map<String, Object> metaAttributes = action.getMetaAttributes(); 239 String actionStatus = (String) metaAttributes.getOrDefault("status", String.valueOf(actionId)); 240 attrs.addCDATAAttribute("status", actionStatus); 241 242 _saxActionType(action, attrs); 243 244 I18nizableText workflowActionLabel = new I18nizableText("application", action.getName()); 245 246 XMLUtils.startElement(contentHandler, "action", attrs); 247 workflowActionLabel.toSAX(contentHandler); 248 XMLUtils.endElement(contentHandler, "action"); 249 250 } 251 } 252 253 private void _saxActionType(ActionDescriptor action, AttributesImpl attrs) 254 { 255 Map<String, Object> metaAttributes = action.getMetaAttributes(); 256 257 String actionType = (String) metaAttributes.get("action-type"); 258 if (actionType != null) 259 { 260 attrs.addCDATAAttribute("type", actionType); 261 } 262 } 263 264 private void _saxMailUsersInformations(FormEntry formEntry, UserIdentity user) throws SAXException 265 { 266 User currentUser = _userManager.getUser(user); 267 268 XMLUtils.createElement(contentHandler, "sender-mail", currentUser.getEmail()); 269 XMLUtils.createElement(contentHandler, "sender-fullname", currentUser.getFullName() + " <" + currentUser.getEmail() + ">"); 270 271 XMLUtils.startElement(contentHandler, "receivers"); 272 User entryUser = _userManager.getUser(formEntry.getUser()); 273 274 XMLUtils.startElement(contentHandler, "receiver"); 275 XMLUtils.createElement(contentHandler, "receiver-mail", entryUser.getEmail()); 276 XMLUtils.createElement(contentHandler, "receiver-fullname", entryUser.getFullName() + " <" + entryUser.getEmail() + ">"); 277 XMLUtils.endElement(contentHandler, "receiver"); 278 279 for (FormQuestion question : _formMailHelper.getQuestionWithMail(formEntry.getForm().getId())) 280 { 281 Optional<String> receiver = _formMailHelper.getReceiver(formEntry, Optional.of(question.getNameForForm())); 282 if (receiver.isPresent()) 283 { 284 XMLUtils.startElement(contentHandler, "receiver"); 285 XMLUtils.createElement(contentHandler, "receiver-mail", receiver.get()); 286 XMLUtils.createElement(contentHandler, "receiver-fullname", question.getTitle() + " <" + receiver.get() + ">"); 287 XMLUtils.endElement(contentHandler, "receiver"); 288 } 289 } 290 XMLUtils.endElement(contentHandler, "receivers"); 291 } 292 293 private record EntriesRecord(List<FormEntry> entries, boolean hasNextEntries) { /** empty */ } 294}