1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.ken.web.spring;
17
18 import java.util.Date;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.log4j.Logger;
29 import org.kuali.rice.ken.bo.Notification;
30 import org.kuali.rice.ken.bo.NotificationChannelReviewer;
31 import org.kuali.rice.ken.document.kew.NotificationWorkflowDocument;
32 import org.kuali.rice.ken.service.NotificationMessageContentService;
33 import org.kuali.rice.ken.service.NotificationRecipientService;
34 import org.kuali.rice.ken.service.NotificationWorkflowDocumentService;
35 import org.kuali.rice.ken.util.NotificationConstants;
36 import org.kuali.rice.ken.util.Util;
37 import org.kuali.rice.kew.dto.NetworkIdDTO;
38 import org.kuali.rice.kew.dto.WorkflowIdDTO;
39 import org.kuali.rice.kew.service.WorkflowDocument;
40 import org.kuali.rice.kim.bo.Person;
41 import org.kuali.rice.kim.service.KIMServiceLocator;
42 import org.kuali.rice.kim.util.KimConstants.KimGroupMemberTypes;
43 import org.springframework.validation.BindException;
44 import org.springframework.validation.ValidationUtils;
45 import org.springframework.web.bind.ServletRequestBindingException;
46 import org.springframework.web.servlet.ModelAndView;
47 import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
48
49
50
51
52
53
54
55 public class AdministerNotificationRequestController extends MultiActionController {
56 private static final Logger LOG = Logger.getLogger(AdministerNotificationRequestController.class);
57
58
59
60
61 public static class AdministerNotificationRequestCommand {
62
63 private Long docId;
64
65
66 private NotificationWorkflowDocument document;
67 private Notification notification;
68 private String renderedContent;
69 private boolean valid = true;
70 private String message;
71
72 public Long getDocId() {
73 return docId;
74 }
75 public void setDocId(Long docId) {
76 this.docId = docId;
77 }
78 public NotificationWorkflowDocument getDocument() {
79 return document;
80 }
81 public void setDocument(NotificationWorkflowDocument document) {
82 this.document = document;
83 }
84 public Notification getNotification() {
85 return notification;
86 }
87 public void setNotification(Notification notification) {
88 this.notification = notification;
89 }
90 public String getRenderedContent() {
91 return renderedContent;
92 }
93 public void setRenderedContent(String renderedContent) {
94 this.renderedContent = renderedContent;
95 }
96 public boolean isValid() {
97 return valid;
98 }
99 public void setValid(boolean valid) {
100 this.valid = valid;
101 }
102 public String getMessage() {
103 return message;
104 }
105 public void setMessage(String message) {
106 this.message = message;
107 }
108 }
109
110 protected NotificationMessageContentService messageContentService;
111 protected NotificationWorkflowDocumentService workflowDocumentService;
112 protected NotificationRecipientService recipientService;
113
114
115
116
117
118 public void setMessageContentService(
119 NotificationMessageContentService notificationMessageContentService) {
120 this.messageContentService = notificationMessageContentService;
121 }
122
123
124
125
126
127 public void setWorkflowDocumentService(
128 NotificationWorkflowDocumentService notificationWorkflowDocumentService) {
129 this.workflowDocumentService = notificationWorkflowDocumentService;
130 }
131
132
133
134
135
136 public void setRecipientService(
137 NotificationRecipientService notificationRecipientService) {
138 this.recipientService = notificationRecipientService;
139 }
140
141
142
143
144
145
146
147
148 private Notification retrieveNotificationForWorkflowDocument(WorkflowDocument document) throws Exception {
149 String notificationAsXml = document.getApplicationContent();
150
151
152 Notification notification = messageContentService.parseSerializedNotificationXml(notificationAsXml.getBytes());
153
154 return notification;
155 }
156
157
158
159
160
161
162
163
164 public ModelAndView view(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) {
165
166 WorkflowIdDTO initiator = new WorkflowIdDTO(request.getRemoteUser());
167
168
169 if (command.getDocId() == null) {
170 throw new RuntimeException("An invalid document ID was recieved from KEW's action list.");
171 }
172
173
174 String view = request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.COMMAND);
175 String standaloneWindow = "true";
176 if(view != null && view.equals(NotificationConstants.NOTIFICATION_DETAIL_VIEWS.INLINE)) {
177 standaloneWindow = "false";
178 }
179
180 NotificationWorkflowDocument document;
181 Map<String, Object> model = new HashMap<String, Object>();
182
183 model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, standaloneWindow);
184 try {
185 document = new NotificationWorkflowDocument(initiator, new Long(command.getDocId()));
186
187 Notification notification = retrieveNotificationForWorkflowDocument(document);
188
189
190 command.setDocument(document);
191 command.setNotification(notification);
192
193 command.setRenderedContent(Util.transformContent(notification));
194
195 LOG.info("notification auto remove date time: " + notification.getAutoRemoveDateTime());
196 if (document.stateIsApproved()) {
197 command.setValid(false);
198 command.setMessage("This notification request has been approved.");
199 } else if (document.stateIsDisapproved()) {
200 command.setMessage("This notification request has been disapproved.");
201 } else if (notification.getAutoRemoveDateTime() != null && notification.getAutoRemoveDateTime().before(new Date(System.currentTimeMillis()))) {
202
203
204
205
206 boolean disapproved = document.stateIsDisapproved();
207 if (!document.stateIsDisapproved()) {
208 List<NotificationChannelReviewer> reviewers = notification.getChannel().getReviewers();
209 String user = null;
210 for (NotificationChannelReviewer reviewer: reviewers) {
211 if (KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.equals(reviewer.getReviewerType())) {
212 if (reviewer.getReviewerId().equals(request.getRemoteUser())) {
213 user = request.getRemoteUser();
214 }
215 } else if (KimGroupMemberTypes.GROUP_MEMBER_TYPE.equals(reviewer.getReviewerType())) {
216
217 String[] members = recipientService.getGroupMembers(reviewer.getReviewerId());
218 for (String member: members) {
219 if (StringUtils.equals(member, request.getRemoteUser())) {
220 user = request.getRemoteUser();
221 break;
222 }
223 }
224 }
225 }
226
227 if (user != null) {
228 new WorkflowDocument(new NetworkIdDTO(user), new Long(command.getDocId())).disapprove("Disapproving notification request. Auto-remove datetime has already passed.");
229 disapproved = true;
230 }
231 }
232 command.setValid(false);
233 if (disapproved) {
234 command.setMessage("This notification request is no longer valid because the Auto-Remove date has already passed. It has been disapproved. Please refresh your action list.");
235 } else {
236 command.setMessage("This notification request is no longer valid because the Auto-Remove date has already passed.");
237 }
238 }
239
240 model.put(getCommandName(command), command);
241 } catch (Exception e) {
242 throw new RuntimeException(e);
243 }
244
245 return new ModelAndView("ViewNotificationRequestDetails", model);
246 }
247
248
249
250
251
252
253
254
255
256 public ModelAndView approve(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) throws ServletException {
257 administerEventNotificationMessage(request, response, command, "approve");
258 Map<String, Object> model = new HashMap<String, Object>();
259 model.put("workflowActionTaken", "Approved");
260 model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW));
261 return new ModelAndView("SendNotificationRequestActionTakenWindow", model);
262 }
263
264
265
266
267
268
269
270
271
272 public ModelAndView disapprove(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) throws ServletException {
273 administerEventNotificationMessage(request, response, command, "disapprove");
274 Map<String, Object> model = new HashMap<String, Object>();
275 model.put("workflowActionTaken", "Disapproved");
276 model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW));
277 return new ModelAndView("SendNotificationRequestActionTakenWindow", model);
278 }
279
280
281
282
283
284
285
286
287
288 public ModelAndView acknowledge(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) throws ServletException {
289 administerEventNotificationMessage(request, response, command, "acknowledge");
290 Map<String, Object> model = new HashMap<String, Object>();
291 model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW));
292 model.put("workflowActionTaken", "Acknowledged");
293 return new ModelAndView("SendNotificationRequestActionTakenWindow", model);
294 }
295
296
297
298
299
300
301
302
303 private void administerEventNotificationMessage(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command, String action) throws ServletException {
304 LOG.debug("remoteUser: " + request.getRemoteUser());
305
306 BindException bindException = new BindException(command, "command");
307 ValidationUtils.rejectIfEmpty(bindException, "docId", "Document id must be specified");
308 if (bindException.hasErrors()) {
309 throw new ServletRequestBindingException("Document id must be specified", bindException);
310 }
311
312
313 WorkflowIdDTO user = new WorkflowIdDTO(request.getRemoteUser());
314
315 try {
316
317 NotificationWorkflowDocument document = new NotificationWorkflowDocument(user, command.getDocId());
318
319 Notification notification = retrieveNotificationForWorkflowDocument(document);
320
321 String initiatorPrincipalId = document.getRouteHeader().getInitiatorPrincipalId();
322 Person initiator = KIMServiceLocator.getPersonService().getPerson(initiatorPrincipalId);
323 String notificationBlurb = notification.getContentType().getName() + " notification submitted by " + initiator.getName() + " for channel " + notification.getChannel().getName();
324 if ("disapprove".equals(action)) {
325 document.disapprove("User " + user.getWorkflowId() + " disapproving " + notificationBlurb);
326 } else if ("approve".equals(action)) {
327 document.approve("User " + user.getWorkflowId() + " approving " + notificationBlurb);
328 } else if ("acknowledge".equals(action)) {
329 document.acknowledge("User " + user.getWorkflowId() + " acknowledging " + notificationBlurb);
330 }
331 } catch (Exception e) {
332 LOG.error("Exception occurred taking action on notification request", e);
333 throw new ServletException("Exception occurred taking action on notification request", e);
334 }
335 }
336 }