001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 */
016 package org.kuali.rice.kew.rule.web;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.apache.struts.action.ActionForm;
020 import org.apache.struts.action.ActionForward;
021 import org.apache.struts.action.ActionMapping;
022 import org.apache.struts.action.ActionMessages;
023 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
024 import org.kuali.rice.kew.api.KewApiConstants;
025 import org.kuali.rice.kew.api.action.ActionRequestStatus;
026 import org.kuali.rice.kew.doctype.bo.DocumentType;
027 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
028 import org.kuali.rice.kew.engine.ActivationContext;
029 import org.kuali.rice.kew.engine.RouteContext;
030 import org.kuali.rice.kew.engine.node.RouteNode;
031 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
032 import org.kuali.rice.kew.exception.WorkflowServiceError;
033 import org.kuali.rice.kew.routeheader.AttributeDocumentContent;
034 import org.kuali.rice.kew.routeheader.DocumentContent;
035 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
036 import org.kuali.rice.kew.routelog.web.RouteLogAction;
037 import org.kuali.rice.kew.routelog.web.RouteLogForm;
038 import org.kuali.rice.kew.rule.FlexRM;
039 import org.kuali.rice.kew.rule.WorkflowRuleAttribute;
040 import org.kuali.rice.kew.rule.bo.RuleAttribute;
041 import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
042 import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
043 import org.kuali.rice.kew.rule.service.RuleTemplateService;
044 import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
045 import org.kuali.rice.kew.service.KEWServiceLocator;
046 import org.kuali.rice.kew.api.KewApiConstants;
047 import org.kuali.rice.kew.web.KewKualiAction;
048 import org.kuali.rice.kns.web.ui.Field;
049 import org.kuali.rice.kns.web.ui.Row;
050 import org.kuali.rice.krad.UserSession;
051 import org.kuali.rice.krad.exception.ValidationException;
052 import org.kuali.rice.krad.util.GlobalVariables;
053
054 import javax.servlet.http.HttpServletRequest;
055 import javax.servlet.http.HttpServletResponse;
056 import java.sql.Timestamp;
057 import java.text.SimpleDateFormat;
058 import java.util.ArrayList;
059 import java.util.Calendar;
060 import java.util.Collections;
061 import java.util.Date;
062 import java.util.HashMap;
063 import java.util.HashSet;
064 import java.util.Iterator;
065 import java.util.List;
066 import java.util.Map;
067 import java.util.Set;
068
069
070 /**
071 * A Struts Action for executing routing reports and retrieving the results.
072 *
073 * @author Kuali Rice Team (rice.collab@kuali.org)
074 */
075 public class RoutingReportAction extends KewKualiAction {
076 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RoutingReportAction.class);
077
078 public static final String DOC_TYPE_REPORTING = "documentType";
079 public static final String TEMPLATE_REPORTING = "template";
080
081 @Override
082 public ActionForward execute(ActionMapping mapping, ActionForm form,
083 HttpServletRequest request, HttpServletResponse response)
084 throws Exception {
085 this.initiateForm(request, form);
086 RoutingReportForm routingForm = (RoutingReportForm)form;
087 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDateRef())) {
088 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
089 routingForm.setEffectiveHour("5");
090 routingForm.setEffectiveMinute("0");
091 routingForm.setAmPm("1");
092 routingForm.setDateRef(sdf.format(new Date()));
093 routingForm.setReportType(TEMPLATE_REPORTING);
094 }
095 if (DOC_TYPE_REPORTING.equals(routingForm.getReportType())) {
096 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDocumentTypeParam())) {
097 throw new RuntimeException("No document type was given");
098 }
099 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getInitiatorPrincipalId())) {
100 throw new RuntimeException("No initiator principal id was given");
101 }
102 if (org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDocumentContent())) {
103 throw new RuntimeException("No document content was given");
104 }
105 } else if (!(TEMPLATE_REPORTING.equals(routingForm.getReportType()))) {
106 // report type is not Document Type or Template Type... error out
107 throw new RuntimeException("The Routing Report type is not set");
108 }
109 return super.execute(mapping, form, request, response);
110 }
111
112 public ActionForward calculateRoute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
113 RoutingReportForm routingForm = (RoutingReportForm) form;
114
115 // this is never actually used??
116 List<WorkflowServiceError> errors = new ArrayList<WorkflowServiceError>();
117
118 if (getDocumentTypeService().findByName(routingForm.getDocumentType()) == null) {
119 GlobalVariables.getMessageMap().putError("Document type is required.", "doctype.documenttypeservice.doctypename.required");
120 }
121 Timestamp date = null;
122 if (!org.apache.commons.lang.StringUtils.isEmpty(routingForm.getDateRef())) {
123 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
124 try {
125 Calendar calendar = Calendar.getInstance();
126 calendar.setTime(sdf.parse(routingForm.getDateRef()));
127 calendar.set(Calendar.HOUR, Integer.parseInt(routingForm.getEffectiveHour()));
128 calendar.set(Calendar.MINUTE, Integer.parseInt(routingForm.getEffectiveMinute()));
129 calendar.set(Calendar.AM_PM, Integer.parseInt(routingForm.getAmPm()));
130 date = new Timestamp(calendar.getTimeInMillis());
131 } catch (Exception e) {
132 LOG.error("error parsing date", e);
133 GlobalVariables.getMessageMap().putError("Invalid date.", "routereport.effectiveDate.invalid");
134 }
135 }
136
137 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
138 throw new ValidationException("Errors populating rule attributes.");
139 }
140
141 DocumentTypeService documentTypeService = (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
142 DocumentType docType = documentTypeService.findByName(routingForm.getDocumentType());
143
144 DocumentRouteHeaderValue routeHeader = new DocumentRouteHeaderValue();
145 routeHeader.setDocumentId("");
146 routeHeader.setDocumentTypeId(docType.getDocumentTypeId());
147 routeHeader.setDocRouteLevel(new Integer(0));
148 routeHeader.setDocVersion(new Integer(KewApiConstants.DocumentContentVersions.CURRENT));
149
150 List<RouteReportRuleTemplateContainer> ruleTemplateContainers = new ArrayList<RouteReportRuleTemplateContainer>();
151 if (routingForm.getReportType().equals(DOC_TYPE_REPORTING)) {
152
153 List routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(docType, true);
154 for (Iterator iter = routeNodes.iterator(); iter.hasNext();) {
155 RouteNode routeNode = (RouteNode) iter.next();
156 if (routeNode.isFlexRM()) {
157 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateName(routeNode.getRouteMethodName());
158 if (ruleTemplate != null) {
159 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate, routeNode));
160 if (ruleTemplate.getDelegationTemplate() != null) {
161 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate.getDelegationTemplate(), routeNode));
162 }
163 }
164 }
165 }
166 } else {
167 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(routingForm.getRuleTemplateId());
168 RouteNode routeNode = new RouteNode();
169 routeNode.setRouteNodeName(ruleTemplate.getName());
170 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate, routeNode));
171 if (ruleTemplate.getDelegationTemplate() != null) {
172 ruleTemplateContainers.add(new RouteReportRuleTemplateContainer(ruleTemplate.getDelegationTemplate(), routeNode));
173 }
174 }
175
176 String xmlDocumentContent = routingForm.getDocumentContent();
177 if (routingForm.getReportType().equals(TEMPLATE_REPORTING)) {
178 List<WorkflowRuleAttribute> attributes = new ArrayList<WorkflowRuleAttribute>();
179 for (RouteReportRuleTemplateContainer ruleTemplateContainer : ruleTemplateContainers) {
180 RuleTemplateBo ruleTemplate = ruleTemplateContainer.ruleTemplate;
181 for (RuleTemplateAttributeBo ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
182 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
183 continue;
184 }
185 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
186
187 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
188 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
189 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
190 }
191 List attValidationErrors = workflowAttribute.validateRoutingData(routingForm.getFields());
192 if (attValidationErrors != null && !attValidationErrors.isEmpty()) {
193 errors.addAll(attValidationErrors);
194 }
195 attributes.add(workflowAttribute);
196 }
197 }
198
199 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
200 throw new ValidationException("errors in search criteria");
201 }
202
203 DocumentContent docContent = new AttributeDocumentContent(attributes);
204 xmlDocumentContent = docContent.getDocContent();
205 }
206
207 routeHeader.setDocContent(xmlDocumentContent);
208 routeHeader.setInitiatorWorkflowId(getUserSession(request).getPrincipalId());
209 routeHeader.setDocRouteStatus(KewApiConstants.ROUTE_HEADER_INITIATED_CD);
210 routeHeader.setDocTitle("Routing Report");
211 routeHeader.setRoutingReport(true);
212 long magicCounter = 0;
213
214 FlexRM flexRM = new FlexRM(date);
215
216 int numberOfRules = 0;
217 int numberOfActionRequests = 0;
218 Set<String> alreadyProcessedRuleTemplateNames = new HashSet<String>();
219 for (Object element : ruleTemplateContainers) {
220 // initialize the RouteContext
221 RouteContext context = RouteContext.createNewRouteContext();
222 context.setActivationContext(new ActivationContext(ActivationContext.CONTEXT_IS_SIMULATION));
223 try {
224 RouteReportRuleTemplateContainer ruleTemplateContainer = (RouteReportRuleTemplateContainer) element;
225 RuleTemplateBo ruleTemplate = ruleTemplateContainer.ruleTemplate;
226 RouteNode routeLevel = ruleTemplateContainer.routeNode;
227
228 if (!alreadyProcessedRuleTemplateNames.contains(ruleTemplate.getName())) {
229 alreadyProcessedRuleTemplateNames.add(ruleTemplate.getName());
230 List<ActionRequestValue> actionRequests = flexRM.getActionRequests(routeHeader, routeLevel, null, ruleTemplate.getName());
231
232 numberOfActionRequests += actionRequests.size();
233 numberOfRules += flexRM.getNumberOfMatchingRules();
234
235 magicCounter = populateActionRequestsWithRouteLevelInformationAndIterateMagicCounter(routeLevel, actionRequests, magicCounter);
236 //routeHeader.getActionRequests().addAll(actionRequests);
237 routeHeader.getSimulatedActionRequests().addAll(actionRequests);
238 }
239 } finally {
240 RouteContext.clearCurrentRouteContext();
241 }
242 }
243
244 if (numberOfActionRequests == 0) {
245 if (numberOfRules == 0) {
246 GlobalVariables.getMessageMap().putError("*", "routereport.noRules");
247 } else {
248 GlobalVariables.getMessageMap().putError("*", "routereport.noMatchingRules");
249 }
250 if (GlobalVariables.getMessageMap().hasErrors()) {
251 throw new ValidationException("errors in search criteria");
252 }
253 }
254
255
256 // PROBLEM HERE!!!!
257 RouteLogForm routeLogForm = new RouteLogForm();
258 routeLogForm.setShowFuture(true);
259 if (StringUtils.isNotBlank(routingForm.getBackUrl())) {
260 routeLogForm.setReturnUrlLocation(routingForm.getBackUrl());
261 }
262 LOG.debug("Value of getDisplayCloseButton " + routingForm.getShowCloseButton());
263 LOG.debug("Value of isDisplayCloseButton " + routingForm.isDisplayCloseButton());
264 routeLogForm.setShowCloseButton(routingForm.isDisplayCloseButton());
265 request.setAttribute("routeHeader", routeHeader);
266 new RouteLogAction().populateRouteLogFormActionRequests(routeLogForm, routeHeader);
267 request.setAttribute("KualiForm", routeLogForm);
268 //END PROBLEM AREA
269
270 //return mapping.findForward("basic");
271 return mapping.findForward("routeLog");
272 }
273
274 private class RouteReportRuleTemplateContainer {
275 public RuleTemplateBo ruleTemplate = null;
276 public RouteNode routeNode = null;
277 public RouteReportRuleTemplateContainer(RuleTemplateBo template, RouteNode node) {
278 this.ruleTemplate = template;
279 this.routeNode = node;
280 }
281 }
282
283 public long populateActionRequestsWithRouteLevelInformationAndIterateMagicCounter(RouteNode routeLevel, List<ActionRequestValue> actionRequests, long magicCounter) {
284
285 for (ActionRequestValue actionRequest : actionRequests) {
286 populateActionRequestsWithRouteLevelInformationAndIterateMagicCounter(routeLevel, actionRequest.getChildrenRequests(), magicCounter);
287 actionRequest.setStatus(ActionRequestStatus.INITIALIZED.getCode());
288 // actionRequest.setRouteMethodName(routeLevel.getRouteMethodName());
289 RouteNodeInstance routeNode = new RouteNodeInstance();
290 routeNode.setRouteNode(routeLevel);
291 actionRequest.setNodeInstance(routeNode);
292 actionRequest.setRouteLevel(new Integer(0));
293 magicCounter++;
294 actionRequest.setActionRequestId(String.valueOf(magicCounter));
295 }
296 return magicCounter;
297 }
298
299 @Override
300 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
301 return mapping.findForward("basic");
302 }
303
304 private ActionMessages initiateForm(HttpServletRequest request, ActionForm form) throws Exception {
305 RoutingReportForm routingReportForm = (RoutingReportForm) form;
306 if (routingReportForm.getReportType() == null) {
307 // no report type means we must check for potential setup
308 if ( (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentTypeParam())) ||
309 (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getInitiatorPrincipalId())) ||
310 (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentContent())) ) {
311 // at least one parameter was passed... attempt to use Doc Type Report
312 routingReportForm.setReportType(DOC_TYPE_REPORTING);
313 } else {
314 // no parameters passed... default to Template Type Rreport
315 routingReportForm.setReportType(TEMPLATE_REPORTING);
316 }
317 }
318
319 if (routingReportForm.getReportType().equals(DOC_TYPE_REPORTING)) {
320 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentTypeParam())) {
321 throw new RuntimeException("Document Type was not given");
322 } else {
323 DocumentType docType = getDocumentTypeService().findByName(routingReportForm.getDocumentTypeParam());
324 if (docType == null) {
325 throw new RuntimeException("Document Type is invalid");
326 }
327 }
328 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getInitiatorPrincipalId())) {
329 throw new RuntimeException("Initiator Principal ID was not given");
330 } else {
331 KEWServiceLocator.getIdentityHelperService().getPrincipal(routingReportForm.getInitiatorPrincipalId());
332 }
333 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentContent())) {
334 throw new RuntimeException("Document Content was not given");
335 }
336
337 if (!org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDocumentType())) {
338 DocumentType docType = getDocumentTypeService().findByName(routingReportForm.getDocumentType());
339 if (docType == null) {
340 throw new RuntimeException("Document Type is missing or invalid");
341 }
342 routingReportForm.getRuleTemplateAttributes().clear();
343 List<RouteNode> routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(docType, true);
344 for (RouteNode routeNode : routeNodes) {
345 if (routeNode.isFlexRM()) {
346 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateName(routeNode.getRouteMethodName());
347 if (ruleTemplate != null) {
348 loadRuleTemplateOnForm(ruleTemplate, routingReportForm, request, false);
349 if (ruleTemplate.getDelegationTemplate() != null) {
350 loadRuleTemplateOnForm(ruleTemplate.getDelegationTemplate(), routingReportForm, request, true);
351 }
352 }
353 }
354 }
355 }
356 // routingReportForm.setShowFields(true);
357 } else if (routingReportForm.getReportType().equals(TEMPLATE_REPORTING)) {
358 routingReportForm.setRuleTemplates(getRuleTemplateService().findAll());
359 if (routingReportForm.getRuleTemplateId() != null) {
360 RuleTemplateBo ruleTemplate = getRuleTemplateService().findByRuleTemplateId(routingReportForm.getRuleTemplateId());
361 routingReportForm.getRuleTemplateAttributes().clear();
362 loadRuleTemplateOnForm(ruleTemplate, routingReportForm, request, false);
363 if (ruleTemplate.getDelegationTemplate() != null) {
364 loadRuleTemplateOnForm(ruleTemplate.getDelegationTemplate(), routingReportForm, request, true);
365 }
366 }
367 }
368 return null;
369 }
370
371 private void loadRuleTemplateOnForm(RuleTemplateBo ruleTemplate, RoutingReportForm routingReportForm, HttpServletRequest request, boolean isDelegate) {
372
373 Map<String, String> fieldValues = new HashMap<String, String>();
374
375 List<RuleTemplateAttributeBo> ruleTemplateAttributes = ruleTemplate.getActiveRuleTemplateAttributes();
376 Collections.sort(ruleTemplateAttributes);
377
378 List<Row> rows = new ArrayList<Row>();
379 for (RuleTemplateAttributeBo ruleTemplateAttribute : ruleTemplateAttributes) {
380 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
381 continue;
382 }
383 WorkflowRuleAttribute workflowAttribute = ruleTemplateAttribute.getWorkflowAttribute();
384
385 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
386 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
387 ((GenericXMLRuleAttribute) workflowAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
388 }
389 for (Row row : workflowAttribute.getRoutingDataRows()) {
390
391 List<Field> fields = new ArrayList<Field>();
392 for (Object element2 : row.getFields()) {
393 Field field = (Field) element2;
394 if (request.getParameter(field.getPropertyName()) != null) {
395 field.setPropertyValue(request.getParameter(field.getPropertyName()));
396 } else if (routingReportForm.getFields() != null && !routingReportForm.getFields().isEmpty()) {
397 field.setPropertyValue((String) routingReportForm.getFields().get(field.getPropertyName()));
398 }
399 fields.add(field);
400 fieldValues.put(field.getPropertyName(), field.getPropertyValue());
401 }
402 }
403
404 workflowAttribute.validateRuleData(fieldValues);// populate attribute
405 List<Row> rdRows = workflowAttribute.getRoutingDataRows();
406 for (Row row : rdRows)
407 {
408 List<Field> fields = new ArrayList<Field>();
409 List<Field> rowFields = row.getFields();
410 for (Field field : rowFields )
411 {
412 if (request.getParameter(field.getPropertyName()) != null) {
413 field.setPropertyValue(request.getParameter(field.getPropertyName()));
414 } else if (routingReportForm.getFields() != null && !routingReportForm.getFields().isEmpty()) {
415 field.setPropertyValue((String) routingReportForm.getFields().get(field.getPropertyName()));
416 }
417 fields.add(field);
418 fieldValues.put(field.getPropertyName(), field.getPropertyValue());
419 }
420 row.setFields(fields);
421 rows.add(row);
422
423 }
424 }
425
426 routingReportForm.getFields().putAll(fieldValues);
427 routingReportForm.getRuleTemplateAttributes().addAll(rows);
428 routingReportForm.setShowFields(true);
429 routingReportForm.setShowViewResults(true);
430 }
431
432 public ActionForward loadTemplate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
433 RoutingReportForm routingReportForm = (RoutingReportForm) form;
434 if (org.apache.commons.lang.StringUtils.isEmpty(routingReportForm.getDateRef())) {
435 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
436 routingReportForm.setEffectiveHour("5");
437 routingReportForm.setEffectiveMinute("0");
438 routingReportForm.setAmPm("1");
439 routingReportForm.setDateRef(sdf.format(new Date()));
440 }
441 return mapping.findForward("basic");
442 }
443
444 private RuleTemplateService getRuleTemplateService() {
445 return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
446 }
447
448 private DocumentTypeService getDocumentTypeService() {
449 return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
450 }
451
452 private UserSession getUserSession(HttpServletRequest request) {
453 return GlobalVariables.getUserSession();
454 }
455
456
457
458
459 }