Coverage Report - org.kuali.rice.kew.actions.ActionTakenEvent
 
Classes in this File Line Coverage Branch Coverage Complexity
ActionTakenEvent
0%
0/101
0%
0/26
1.719
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  *
 4  
  *
 5  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  * http://www.opensource.org/licenses/ecl2.php
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.kuali.rice.kew.actions;
 18  
 
 19  
 import org.apache.log4j.Logger;
 20  
 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
 21  
 import org.kuali.rice.kew.actionrequest.KimGroupRecipient;
 22  
 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient;
 23  
 import org.kuali.rice.kew.actionrequest.Recipient;
 24  
 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
 25  
 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
 26  
 import org.kuali.rice.kew.api.WorkflowRuntimeException;
 27  
 import org.kuali.rice.kew.docsearch.service.SearchableAttributeProcessingService;
 28  
 import org.kuali.rice.kew.engine.RouteContext;
 29  
 import org.kuali.rice.kew.exception.InvalidActionTakenException;
 30  
 import org.kuali.rice.kew.messaging.MessageServiceNames;
 31  
 import org.kuali.rice.kew.messaging.RouteDocumentMessageService;
 32  
 import org.kuali.rice.kew.postprocessor.DocumentRouteStatusChange;
 33  
 import org.kuali.rice.kew.postprocessor.PostProcessor;
 34  
 import org.kuali.rice.kew.postprocessor.ProcessDocReport;
 35  
 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
 36  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 37  
 import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
 38  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 39  
 import org.kuali.rice.ksb.messaging.service.KSBXMLService;
 40  
 
 41  
 import javax.xml.namespace.QName;
 42  
 import java.util.List;
 43  
 
 44  
 
 45  
 /**
 46  
  * Super class containing mostly often used methods by all actions. Holds common
 47  
  * state as well, {@link DocumentRouteHeaderValue} document,
 48  
  * {@link ActionTakenValue} action taken (once saved), {@link PrincipalContract} principal
 49  
  * that has taken the action
 50  
  *
 51  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 52  
  */
 53  
 public abstract class ActionTakenEvent {
 54  
 
 55  0
         private static final Logger LOG = Logger.getLogger(ActionTakenEvent.class);
 56  
 
 57  
         /**
 58  
          * Used when saving an ActionTakenValue, and for validation in validateActionRules
 59  
          */
 60  
         private String actionTakenCode;
 61  
 
 62  
         protected final String annotation;
 63  
 
 64  
         protected DocumentRouteHeaderValue routeHeader;
 65  
 
 66  
         private final PrincipalContract principal;
 67  
 
 68  
     private final boolean runPostProcessorLogic;
 69  
     
 70  
     private List<String> groupIdsForPrincipal;
 71  
     
 72  
 
 73  0
     private boolean queueDocumentAfterAction = true;
 74  
 
 75  
 
 76  
         public ActionTakenEvent(String actionTakenCode, DocumentRouteHeaderValue routeHeader, PrincipalContract principal) {
 77  0
                 this(actionTakenCode, routeHeader, principal, null, true);
 78  0
         }
 79  
 
 80  
     public ActionTakenEvent(String actionTakenCode, DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation) {
 81  0
         this(actionTakenCode, routeHeader, principal, annotation, true);
 82  0
     }
 83  
 
 84  0
         public ActionTakenEvent(String actionTakenCode, DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation, boolean runPostProcessorLogic) {
 85  0
             this.actionTakenCode = actionTakenCode;
 86  0
             this.routeHeader = routeHeader;
 87  0
         this.principal = principal;
 88  0
         this.annotation = annotation == null ? "" : annotation;
 89  0
                 this.runPostProcessorLogic = runPostProcessorLogic;
 90  0
                 this.queueDocumentAfterAction = true;
 91  0
         }
 92  
 
 93  
         public ActionRequestService getActionRequestService() {
 94  0
                 return (ActionRequestService) KEWServiceLocator.getService(KEWServiceLocator.ACTION_REQUEST_SRV);
 95  
         }
 96  
 
 97  
         public DocumentRouteHeaderValue getRouteHeader() {
 98  0
                 return routeHeader;
 99  
         }
 100  
 
 101  
         public void setRouteHeader(DocumentRouteHeaderValue routeHeader) {
 102  0
                 this.routeHeader = routeHeader;
 103  0
         }
 104  
 
 105  
         public PrincipalContract getPrincipal() {
 106  0
                 return principal;
 107  
         }
 108  
 
 109  
         /**
 110  
          * Code of the action performed by the user
 111  
          *
 112  
          * Method may be overriden is action performed will be different than action
 113  
          * taken
 114  
      * @return
 115  
      */
 116  
         protected String getActionPerformedCode() {
 117  0
                 return getActionTakenCode();
 118  
         }
 119  
 
 120  
         /**
 121  
          * Validates whether or not this action is valid for the given principal
 122  
          * and DocumentRouteHeaderValue.
 123  
          */
 124  
         protected boolean isActionValid() {
 125  0
                 return org.apache.commons.lang.StringUtils.isEmpty(validateActionRules());
 126  
         }
 127  
 
 128  
         /**
 129  
          * Placeholder for validation rules for each action
 130  
          *
 131  
          * @return error message string of specific error message
 132  
          */
 133  
         public abstract String validateActionRules();
 134  
         public abstract String validateActionRules(List<ActionRequestValue> actionRequests);
 135  
         
 136  
         /**
 137  
          * Filters action requests based on if they occur after the given requestCode, and if they relate to this
 138  
          * event's principal
 139  
          * @param actionRequests the List of ActionRequestValues to filter
 140  
          * @param requestCode the request code for all ActionRequestValues to be after
 141  
          * @return the filtered List of ActionRequestValues
 142  
          */
 143  
         public List<ActionRequestValue> filterActionRequestsByCode(List<ActionRequestValue> actionRequests, String requestCode) {
 144  0
                 return getActionRequestService().filterActionRequestsByCode(actionRequests, getPrincipal().getPrincipalId(), getGroupIdsForPrincipal(), requestCode);
 145  
         }
 146  
 
 147  
         protected boolean isActionCompatibleRequest(List<ActionRequestValue> requests) {
 148  0
                 LOG.debug("isActionCompatibleRequest() Default method = returning true");
 149  0
                 return true;
 150  
         }
 151  
 
 152  
         public void performAction() throws InvalidActionTakenException {
 153  0
             recordAction();
 154  0
             if (queueDocumentAfterAction) {
 155  0
                     queueDocumentProcessing();
 156  
             }
 157  
 
 158  0
         }
 159  
 
 160  
         protected abstract void recordAction() throws InvalidActionTakenException;
 161  
 
 162  
         public void performDeferredAction() {
 163  
 
 164  0
         }
 165  
 
 166  
         protected void updateSearchableAttributesIfPossible() {
 167  
                 // queue the document up so that it can be indexed for searching if it
 168  
                 // has searchable attributes
 169  0
                 RouteContext routeContext = RouteContext.getCurrentRouteContext();
 170  0
                 if (routeHeader.getDocumentType().hasSearchableAttributes() && !routeContext.isSearchIndexingRequestedForContext()) {
 171  0
                         routeContext.requestSearchIndexingForContext();
 172  
                         
 173  0
                         SearchableAttributeProcessingService searchableAttService = (SearchableAttributeProcessingService) MessageServiceNames.getSearchableAttributeService(getRouteHeader());
 174  0
                         searchableAttService.indexDocument(getDocumentId());
 175  
                 }
 176  0
         }
 177  
 
 178  
         protected void notifyActionTaken(ActionTakenValue actionTaken) {
 179  0
             if (!isRunPostProcessorLogic()) {
 180  0
                 return;
 181  
             }
 182  0
                 if (actionTaken == null) {
 183  0
                         return;
 184  
                 }
 185  
                 try {
 186  0
                         LOG.debug("Notifying post processor of action taken");
 187  0
                         PostProcessor postProcessor = routeHeader.getDocumentType().getPostProcessor();
 188  0
                         ProcessDocReport report = postProcessor.doActionTaken(new org.kuali.rice.kew.postprocessor.ActionTakenEvent(routeHeader.getDocumentId(), routeHeader.getAppDocId(), actionTaken));
 189  0
                         if (!report.isSuccess()) {
 190  0
                                 LOG.warn(report.getMessage(), report.getProcessException());
 191  0
                                 throw new InvalidActionTakenException(report.getMessage());
 192  
                         }
 193  
 
 194  0
                 } catch (Exception ex) {
 195  0
                     processPostProcessorException(ex);
 196  0
                 }
 197  0
         }
 198  
 
 199  
         protected void notifyStatusChange(String newStatusCode, String oldStatusCode) throws InvalidActionTakenException {
 200  0
         if (!isRunPostProcessorLogic()) {
 201  0
             return;
 202  
         }
 203  0
                 DocumentRouteStatusChange statusChangeEvent = new DocumentRouteStatusChange(routeHeader.getDocumentId(), routeHeader.getAppDocId(), oldStatusCode, newStatusCode);
 204  
                 try {
 205  0
                         LOG.debug("Notifying post processor of status change " + oldStatusCode + "->" + newStatusCode);
 206  0
                         PostProcessor postProcessor = routeHeader.getDocumentType().getPostProcessor();
 207  0
                         ProcessDocReport report = postProcessor.doRouteStatusChange(statusChangeEvent);
 208  0
                         if (!report.isSuccess()) {
 209  0
                                 LOG.warn(report.getMessage(), report.getProcessException());
 210  0
                                 throw new InvalidActionTakenException(report.getMessage());
 211  
                         }
 212  0
                 } catch (Exception ex) {
 213  0
                     processPostProcessorException(ex);
 214  0
                 }
 215  0
         }
 216  
 
 217  
         /**
 218  
          * Asynchronously queues the documented to be processed by the workflow engine.
 219  
          */
 220  
         protected void queueDocumentProcessing() {
 221  0
                 QName documentServiceName = new QName(getRouteHeader().getDocumentType().getApplicationId(), MessageServiceNames.DOCUMENT_ROUTING_SERVICE);
 222  0
                 KSBXMLService documentRoutingService = (KSBXMLService) MessageServiceNames.getServiceAsynchronously(documentServiceName, getRouteHeader());
 223  
                 try {
 224  
 //                        String content = String.valueOf(getDocumentId());
 225  0
                         RouteDocumentMessageService.RouteMessageXmlElement element = new RouteDocumentMessageService.RouteMessageXmlElement(getDocumentId(),isRunPostProcessorLogic(), RouteContext.getCurrentRouteContext().isSearchIndexingRequestedForContext());
 226  0
                         String content = element.translate();
 227  0
                         documentRoutingService.invoke(content);
 228  0
                 } catch (Exception e) {
 229  0
                     processPostProcessorException(e);
 230  0
                 }
 231  0
         }
 232  
 
 233  
         protected ActionTakenValue saveActionTaken() {
 234  0
             return saveActionTaken(Boolean.TRUE);
 235  
         }
 236  
 
 237  
         protected ActionTakenValue saveActionTaken(Boolean currentInd) {
 238  0
                 return saveActionTaken(currentInd, null);
 239  
         }
 240  
 
 241  
         protected ActionTakenValue saveActionTaken(Recipient delegator) {
 242  0
             return saveActionTaken(Boolean.TRUE, delegator);
 243  
         }
 244  
 
 245  
         protected ActionTakenValue saveActionTaken(Boolean currentInd, Recipient delegator) {
 246  0
                 ActionTakenValue val = new ActionTakenValue();
 247  0
                 val.setActionTaken(getActionTakenCode());
 248  0
                 val.setAnnotation(annotation);
 249  0
                 val.setDocVersion(routeHeader.getDocVersion());
 250  0
                 val.setDocumentId(routeHeader.getDocumentId());
 251  0
                 val.setPrincipalId(principal.getPrincipalId());
 252  0
                 if (delegator instanceof KimPrincipalRecipient) {
 253  0
                         val.setDelegatorPrincipalId(((KimPrincipalRecipient)delegator).getPrincipalId());
 254  0
                 } else if (delegator instanceof KimGroupRecipient) {
 255  0
                         val.setDelegatorGroupId(((KimGroupRecipient) delegator).getGroupId());
 256  
                 }
 257  
                 //val.setRouteHeader(routeHeader);
 258  0
                 val.setCurrentIndicator(currentInd);
 259  0
                 KEWServiceLocator.getActionTakenService().saveActionTaken(val);
 260  0
                 return val;
 261  
         }
 262  
 
 263  
         /**
 264  
          * Returns the highest priority delegator in the list of action requests.
 265  
          */
 266  
         protected Recipient findDelegatorForActionRequests(List actionRequests) {
 267  0
                 return getActionRequestService().findDelegator(actionRequests);
 268  
         }
 269  
 
 270  
         public String getActionTakenCode() {
 271  0
                 return actionTakenCode;
 272  
         }
 273  
 
 274  
         protected void setActionTakenCode(String string) {
 275  0
                 actionTakenCode = string;
 276  0
         }
 277  
 
 278  
         protected String getDocumentId() {
 279  0
                 return this.routeHeader.getDocumentId();
 280  
         }
 281  
 
 282  
         /*protected void delete() {
 283  
             KEWServiceLocator.getActionTakenService().delete(actionTaken);
 284  
         }*/
 285  
 
 286  
         protected boolean isRunPostProcessorLogic() {
 287  0
         return this.runPostProcessorLogic;
 288  
     }
 289  
         
 290  
         protected List<String> getGroupIdsForPrincipal() {
 291  0
                 if (groupIdsForPrincipal == null) {
 292  0
                         groupIdsForPrincipal = KimApiServiceLocator.getGroupService().getGroupIdsForPrincipal(getPrincipal().getPrincipalId());
 293  
                 }
 294  0
                 return groupIdsForPrincipal;
 295  
         }
 296  
 
 297  
 
 298  
         public void setQueueDocumentAfterAction(boolean queueDocumentAfterAction) {
 299  0
                 this.queueDocumentAfterAction = queueDocumentAfterAction;
 300  0
         }
 301  
 
 302  
         private void processPostProcessorException(Exception e) {
 303  0
         if (e instanceof RuntimeException) {
 304  0
             throw (RuntimeException)e;
 305  
         }
 306  0
         throw new WorkflowRuntimeException(e);
 307  
         }
 308  
 
 309  
         
 310  
 }