1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.rule.web;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.struts.action.ActionForm;
20 import org.apache.struts.action.ActionForward;
21 import org.apache.struts.action.ActionMapping;
22 import org.apache.struts.action.ActionMessages;
23 import org.kuali.rice.core.api.uif.RemotableAttributeError;
24 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
25 import org.kuali.rice.kew.api.KewApiConstants;
26 import org.kuali.rice.kew.api.action.ActionRequestStatus;
27 import org.kuali.rice.kew.doctype.bo.DocumentType;
28 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
29 import org.kuali.rice.kew.engine.ActivationContext;
30 import org.kuali.rice.kew.engine.RouteContext;
31 import org.kuali.rice.kew.engine.node.RouteNode;
32 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
33 import org.kuali.rice.kew.exception.WorkflowServiceError;
34 import org.kuali.rice.kew.routeheader.AttributeDocumentContent;
35 import org.kuali.rice.kew.routeheader.DocumentContent;
36 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
37 import org.kuali.rice.kew.routelog.web.RouteLogAction;
38 import org.kuali.rice.kew.routelog.web.RouteLogForm;
39 import org.kuali.rice.kew.rule.FlexRM;
40 import org.kuali.rice.kew.rule.WorkflowRuleAttribute;
41 import org.kuali.rice.kew.rule.bo.RuleAttribute;
42 import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
43 import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
44 import org.kuali.rice.kew.rule.service.RuleTemplateService;
45 import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
46 import org.kuali.rice.kew.service.KEWServiceLocator;
47 import org.kuali.rice.kew.api.KewApiConstants;
48 import org.kuali.rice.kew.web.KewKualiAction;
49 import org.kuali.rice.kns.web.ui.Field;
50 import org.kuali.rice.kns.web.ui.Row;
51 import org.kuali.rice.krad.UserSession;
52 import org.kuali.rice.krad.exception.ValidationException;
53 import org.kuali.rice.krad.util.GlobalVariables;
54
55 import javax.servlet.http.HttpServletRequest;
56 import javax.servlet.http.HttpServletResponse;
57 import java.sql.Timestamp;
58 import java.text.SimpleDateFormat;
59 import java.util.ArrayList;
60 import java.util.Calendar;
61 import java.util.Collections;
62 import java.util.Date;
63 import java.util.HashMap;
64 import java.util.HashSet;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.Set;
69
70
71
72
73
74
75
76 public class RoutingReportAction extends KewKualiAction {
77 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RoutingReportAction.class);
78
79 public static final String DOC_TYPE_REPORTING = "documentType";
80 public static final String TEMPLATE_REPORTING = "template";
81
82 @Override
83 public ActionForward execute(ActionMapping mapping, ActionForm form,
84 HttpServletRequest request, HttpServletResponse response)
85 throws Exception {
86 this.initiateForm(request, form);
87 RoutingReportForm routingForm = (RoutingReportForm)form;
88 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDateRef())) {
89 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
90 routingForm.setEffectiveHour("5");
91 routingForm.setEffectiveMinute("0");
92 routingForm.setAmPm("1");
93 routingForm.setDateRef(sdf.format(new Date()));
94 routingForm.setReportType(TEMPLATE_REPORTING);
95 }
96 if (DOC_TYPE_REPORTING.equals(routingForm.getReportType())) {
97 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDocumentTypeParam())) {
98 throw new RuntimeException("No document type was given");
99 }
100 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getInitiatorPrincipalId())) {
101 throw new RuntimeException("No initiator principal id was given");
102 }
103 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDocumentContent())) {
104 throw new RuntimeException("No document content was given");
105 }
106 } else if (!(TEMPLATE_REPORTING.equals(routingForm.getReportType()))) {
107
108 throw new RuntimeException("The Routing Report type is not set");
109 }
110 return super.execute(mapping, form, request, response);
111 }
112
113 public ActionForward calculateRoute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
114 RoutingReportForm routingForm = (RoutingReportForm) form;
115
116
117 List<RemotableAttributeError> errors = new ArrayList<RemotableAttributeError>();
118
119 if (getDocumentTypeService().findByName(routingForm.getDocumentType()) == null) {
120 GlobalVariables.getMessageMap().putError("Document type is required.", "doctype.documenttypeservice.doctypename.required");
121 }
122 Timestamp date = null;
123 if (!org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDateRef())) {
124 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
125 try {
126 Calendar calendar = Calendar.getInstance();
127 calendar.setTime(sdf.parse(routingForm.getDateRef()));
128 calendar.set(Calendar.HOUR, Integer.parseInt(routingForm.getEffectiveHour()));
129 calendar.set(Calendar.MINUTE, Integer.parseInt(routingForm.getEffectiveMinute()));
130 calendar.set(Calendar.AM_PM, Integer.parseInt(routingForm.getAmPm()));
131 date = new Timestamp(calendar.getTimeInMillis());
132 } catch (Exception e) {
133 LOG.error("error parsing date", e);
134 GlobalVariables.getMessageMap().putError("Invalid date.", "routereport.effectiveDate.invalid");
135 }
136 }
137
138 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
139 throw new ValidationException("Errors populating rule attributes.");
140 }
141
142 DocumentTypeService documentTypeService = (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
143 DocumentType docType = documentTypeService.findByName(routingForm.getDocumentType());
144
145 DocumentRouteHeaderValue routeHeader = new DocumentRouteHeaderValue();
146 routeHeader.setDocumentId("");
147 routeHeader.setDocumentTypeId(docType.getDocumentTypeId());
148 routeHeader.setDocRouteLevel(new Integer(0));
149 routeHeader.setDocVersion(new Integer(KewApiConstants.DocumentContentVersions.CURRENT));
150
151 List<RouteReportRuleTemplateContainer> ruleTemplateContainers = new ArrayList<RouteReportRuleTemplateContainer>();
152 if (routingForm.getReportType().equals(DOC_TYPE_REPORTING)) {
153
154 List routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(docType, true);
155 for (Iterator iter = routeNodes.iterator(); iter.hasNext();) {
156 RouteNode routeNode = (RouteNode) iter.next();
157 if (routeNode.isFlexRM()) {
158 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateName(routeNode.getRouteMethodName());
159 if (ruleTemplate != null) {
160 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate, routeNode));
161 if (ruleTemplate.getDelegationTemplate() != null) {
162 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate.getDelegationTemplate(), routeNode));
163 }
164 }
165 }
166 }
167 } else {
168 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(routingForm.getRuleTemplateId());
169 RouteNode routeNode = new RouteNode();
170 routeNode.setRouteNodeName(ruleTemplate.getName());
171 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate, routeNode));
172 if (ruleTemplate.getDelegationTemplate() != null) {
173 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate.getDelegationTemplate(), routeNode));
174 }
175 }
176
177 String xmlDocumentContent = routingForm.getDocumentContent();
178 if (routingForm.getReportType().equals(TEMPLATE_REPORTING)) {
179 List<WorkflowRuleAttribute> attributes = new ArrayList<WorkflowRuleAttribute>();
180 for (RouteReportRuleTemplateContainer ruleTemplateContainer : ruleTemplateContainers) {
181 RuleTemplateBo ruleTemplate = ruleTemplateContainer.ruleTemplate;
182 for (RuleTemplateAttributeBo ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
183 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
184 continue;
185 }
186 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
187
188 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
189 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
190 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
191 }
192 List<RemotableAttributeError> attValidationErrors = workflowAttribute.validateRoutingData(routingForm.getFields());
193 if (attValidationErrors != null && !attValidationErrors.isEmpty()) {
194 errors.addAll(attValidationErrors);
195 }
196 attributes.add(workflowAttribute);
197 }
198 }
199
200 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
201 throw new ValidationException("errors in search criteria");
202 }
203
204 DocumentContent docContent = new AttributeDocumentContent(attributes);
205 xmlDocumentContent = docContent.getDocContent();
206 }
207
208 routeHeader.setDocContent(xmlDocumentContent);
209 routeHeader.setInitiatorWorkflowId(getUserSession(request).getPrincipalId());
210 routeHeader.setDocRouteStatus(KewApiConstants.ROUTE_HEADER_INITIATED_CD);
211 routeHeader.setDocTitle("Routing Report");
212 routeHeader.setRoutingReport(true);
213 long magicCounter = 0;
214
215 FlexRM flexRM = new FlexRM(date);
216
217 int numberOfRules = 0;
218 int numberOfActionRequests = 0;
219 Set<String> alreadyProcessedRuleTemplateNames = new HashSet<String>();
220 for (Object element : ruleTemplateContainers) {
221
222 RouteContext context = RouteContext.createNewRouteContext();
223 context.setActivationContext(new ActivationContext(ActivationContext.CONTEXT_IS_SIMULATION));
224 try {
225 RouteReportRuleTemplateContainer ruleTemplateContainer = (RouteReportRuleTemplateContainer) element;
226 RuleTemplateBo ruleTemplate = ruleTemplateContainer.ruleTemplate;
227 RouteNode routeLevel = ruleTemplateContainer.routeNode;
228
229 if (!alreadyProcessedRuleTemplateNames.contains(ruleTemplate.getName())) {
230 alreadyProcessedRuleTemplateNames.add(ruleTemplate.getName());
231 List<ActionRequestValue> actionRequests = flexRM.getActionRequests(routeHeader, routeLevel, null, ruleTemplate.getName());
232
233 numberOfActionRequests += actionRequests.size();
234 numberOfRules += flexRM.getNumberOfMatchingRules();
235
236 magicCounter = populateActionRequestsWithRouteLevelInformationAndIterateMagicCounter(routeLevel, actionRequests, magicCounter);
237
238 routeHeader.getSimulatedActionRequests().addAll(actionRequests);
239 }
240 } finally {
241 RouteContext.clearCurrentRouteContext();
242 }
243 }
244
245 if (numberOfActionRequests == 0) {
246 if (numberOfRules == 0) {
247 GlobalVariables.getMessageMap().putError("*", "routereport.noRules");
248 } else {
249 GlobalVariables.getMessageMap().putError("*", "routereport.noMatchingRules");
250 }
251 if (GlobalVariables.getMessageMap().hasErrors()) {
252 throw new ValidationException("errors in search criteria");
253 }
254 }
255
256
257
258 RouteLogForm routeLogForm = new RouteLogForm();
259 routeLogForm.setShowFuture(true);
260 if (StringUtils.isNotBlank(routingForm.getBackUrl())) {
261 routeLogForm.setReturnUrlLocation(routingForm.getBackUrl());
262 }
263 LOG.debug("Value of getDisplayCloseButton " + routingForm.getShowCloseButton());
264 LOG.debug("Value of isDisplayCloseButton " + routingForm.isDisplayCloseButton());
265 routeLogForm.setShowCloseButton(routingForm.isDisplayCloseButton());
266 request.setAttribute("routeHeader", routeHeader);
267 new RouteLogAction().populateRouteLogFormActionRequests(routeLogForm, routeHeader);
268 request.setAttribute("KualiForm", routeLogForm);
269
270
271
272 return mapping.findForward("routeLog");
273 }
274
275 private class RouteReportRuleTemplateContainer {
276 public RuleTemplateBo ruleTemplate = null;
277 public RouteNode routeNode = null;
278 public RouteReportRuleTemplateContainer(RuleTemplateBo template, RouteNode node) {
279 this.ruleTemplate = template;
280 this.routeNode = node;
281 }
282 }
283
284 public long populateActionRequestsWithRouteLevelInformationAndIterateMagicCounter(RouteNode routeLevel, List<ActionRequestValue> actionRequests, long magicCounter) {
285
286 for (ActionRequestValue actionRequest : actionRequests) {
287 populateActionRequestsWithRouteLevelInformationAndIterateMagicCounter(routeLevel, actionRequest.getChildrenRequests(), magicCounter);
288 actionRequest.setStatus(ActionRequestStatus.INITIALIZED.getCode());
289
290 RouteNodeInstance routeNode = new RouteNodeInstance();
291 routeNode.setRouteNode(routeLevel);
292 actionRequest.setNodeInstance(routeNode);
293 actionRequest.setRouteLevel(new Integer(0));
294 magicCounter++;
295 actionRequest.setActionRequestId(String.valueOf(magicCounter));
296 }
297 return magicCounter;
298 }
299
300 @Override
301 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
302 return mapping.findForward("basic");
303 }
304
305 private ActionMessages initiateForm(HttpServletRequest request, ActionForm form) throws Exception {
306 RoutingReportForm routingReportForm = (RoutingReportForm) form;
307 if (routingReportForm.getReportType() == null) {
308
309 if ( (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentTypeParam())) ||
310 (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getInitiatorPrincipalId())) ||
311 (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentContent())) ) {
312
313 routingReportForm.setReportType(DOC_TYPE_REPORTING);
314 } else {
315
316 routingReportForm.setReportType(TEMPLATE_REPORTING);
317 }
318 }
319
320 if (routingReportForm.getReportType().equals(DOC_TYPE_REPORTING)) {
321 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentTypeParam())) {
322 throw new RuntimeException("Document Type was not given");
323 } else {
324 DocumentType docType = getDocumentTypeService().findByName(routingReportForm.getDocumentTypeParam());
325 if (docType == null) {
326 throw new RuntimeException("Document Type is invalid");
327 }
328 }
329 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getInitiatorPrincipalId())) {
330 throw new RuntimeException("Initiator Principal ID was not given");
331 } else {
332 KEWServiceLocator.getIdentityHelperService().getPrincipal(routingReportForm.getInitiatorPrincipalId());
333 }
334 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentContent())) {
335 throw new RuntimeException("Document Content was not given");
336 }
337
338 if (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentType())) {
339 DocumentType docType = getDocumentTypeService().findByName(routingReportForm.getDocumentType());
340 if (docType == null) {
341 throw new RuntimeException("Document Type is missing or invalid");
342 }
343 routingReportForm.getRuleTemplateAttributes().clear();
344 List<RouteNode> routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(docType, true);
345 for (RouteNode routeNode : routeNodes) {
346 if (routeNode.isFlexRM()) {
347 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateName(routeNode.getRouteMethodName());
348 if (ruleTemplate != null) {
349 loadRuleTemplateOnForm(ruleTemplate, routingReportForm, request, false);
350 if (ruleTemplate.getDelegationTemplate() != null) {
351 loadRuleTemplateOnForm(ruleTemplate.getDelegationTemplate(), routingReportForm, request, true);
352 }
353 }
354 }
355 }
356 }
357
358 } else if (routingReportForm.getReportType().equals(TEMPLATE_REPORTING)) {
359 routingReportForm.setRuleTemplates(getRuleTemplateService().findAll());
360 if (routingReportForm.getRuleTemplateId() != null) {
361 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(routingReportForm.getRuleTemplateId());
362 routingReportForm.getRuleTemplateAttributes().clear();
363 loadRuleTemplateOnForm(ruleTemplate, routingReportForm, request, false);
364 if (ruleTemplate.getDelegationTemplate() != null) {
365 loadRuleTemplateOnForm(ruleTemplate.getDelegationTemplate(), routingReportForm, request, true);
366 }
367 }
368 }
369 return null;
370 }
371
372 private void loadRuleTemplateOnForm(RuleTemplateBo ruleTemplate, RoutingReportForm routingReportForm, HttpServletRequest request, boolean isDelegate) {
373
374 Map<String, String> fieldValues = new HashMap<String, String>();
375
376 List<RuleTemplateAttributeBo> ruleTemplateAttributes = ruleTemplate.getActiveRuleTemplateAttributes();
377 Collections.sort(ruleTemplateAttributes);
378
379 List<Row> rows = new ArrayList<Row>();
380 for (RuleTemplateAttributeBo ruleTemplateAttribute : ruleTemplateAttributes) {
381 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
382 continue;
383 }
384 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
385
386 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
387 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
388 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
389 }
390 for (Row row : workflowAttribute.getRoutingDataRows()) {
391
392 List<Field> fields = new ArrayList<Field>();
393 for (Object element2 : row.getFields()) {
394 Field field = (Field) element2;
395 if (request.getParameter(field.getPropertyName()) != null) {
396 field.setPropertyValue(request.getParameter(field.getPropertyName()));
397 } else if (routingReportForm.getFields() != null && !routingReportForm.getFields().isEmpty()) {
398 field.setPropertyValue((String) routingReportForm.getFields().get(field.getPropertyName()));
399 }
400 fields.add(field);
401 fieldValues.put(field.getPropertyName(), field.getPropertyValue());
402 }
403 }
404
405 workflowAttribute.validateRuleData(fieldValues);
406 List<Row> rdRows = workflowAttribute.getRoutingDataRows();
407 for (Row row : rdRows)
408 {
409 List<Field> fields = new ArrayList<Field>();
410 List<Field> rowFields = row.getFields();
411 for (Field field : rowFields )
412 {
413 if (request.getParameter(field.getPropertyName()) != null) {
414 field.setPropertyValue(request.getParameter(field.getPropertyName()));
415 } else if (routingReportForm.getFields() != null && !routingReportForm.getFields().isEmpty()) {
416 field.setPropertyValue((String) routingReportForm.getFields().get(field.getPropertyName()));
417 }
418 fields.add(field);
419 fieldValues.put(field.getPropertyName(), field.getPropertyValue());
420 }
421 row.setFields(fields);
422 rows.add(row);
423
424 }
425 }
426
427 routingReportForm.getFields().putAll(fieldValues);
428 routingReportForm.getRuleTemplateAttributes().addAll(rows);
429 routingReportForm.setShowFields(true);
430 routingReportForm.setShowViewResults(true);
431 }
432
433 public ActionForward loadTemplate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
434 RoutingReportForm routingReportForm = (RoutingReportForm) form;
435 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDateRef())) {
436 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
437 routingReportForm.setEffectiveHour("5");
438 routingReportForm.setEffectiveMinute("0");
439 routingReportForm.setAmPm("1");
440 routingReportForm.setDateRef(sdf.format(new Date()));
441 }
442 return mapping.findForward("basic");
443 }
444
445 private RuleTemplateService getRuleTemplateService() {
446 return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
447 }
448
449 private DocumentTypeService getDocumentTypeService() {
450 return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
451 }
452
453 private UserSession getUserSession(HttpServletRequest request) {
454 return GlobalVariables.getUserSession();
455 }
456
457
458
459
460 }