001/** 002 * Copyright 2005-2018 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 */ 016package org.kuali.rice.krad.document; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 020import org.kuali.rice.coreservice.framework.parameter.ParameterService; 021import org.kuali.rice.kew.api.KewApiServiceLocator; 022import org.kuali.rice.kew.api.WorkflowDocument; 023import org.kuali.rice.kew.api.action.ActionRequest; 024import org.kuali.rice.kew.api.action.ActionRequestType; 025import org.kuali.rice.kew.api.action.ActionType; 026import org.kuali.rice.kew.api.document.DocumentStatus; 027import org.kuali.rice.krad.uif.view.RequestAuthorizationCache; 028import org.kuali.rice.krad.util.GlobalVariables; 029import org.kuali.rice.krad.util.KRADConstants; 030import org.kuali.rice.krad.util.KRADUtils; 031 032import java.io.Serializable; 033 034/** 035 * @author Kuali Rice Team (rice.collab@kuali.org) 036 */ 037public class DocumentPresentationControllerBase implements DocumentPresentationController, Serializable { 038 private static final long serialVersionUID = -9181864754090276024L; 039 040 private static transient ParameterService parameterService; 041 042 private DocumentRequestAuthorizationCache documentRequestAuthorizationCache; 043 044 public boolean canInitiate(String documentTypeName) { 045 return true; 046 } 047 048 public boolean canEdit(Document document) { 049 boolean canEdit = false; 050 051 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 052 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 053 054 if (workflowDocumentInfo.isInitiated() 055 || workflowDocumentInfo.isSaved() 056 || workflowDocumentInfo.isEnroute() 057 || workflowDocumentInfo.isException()) { 058 canEdit = true; 059 } 060 061 return canEdit; 062 } 063 064 public boolean canAnnotate(Document document) { 065 return true; 066 } 067 068 public boolean canReload(Document document) { 069 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 070 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 071 072 return (canEdit(document) && !workflowDocumentInfo.isInitiated()); 073 074 } 075 076 public boolean canClose(Document document) { 077 return false; 078 } 079 080 public boolean canSave(Document document) { 081 return canEdit(document); 082 } 083 084 public boolean canRoute(Document document) { 085 boolean canRoute = false; 086 087 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 088 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 089 090 if (workflowDocumentInfo.isInitiated() || workflowDocumentInfo.isSaved()) { 091 canRoute = true; 092 } 093 094 return canRoute; 095 } 096 097 public boolean canCancel(Document document) { 098 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 099 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 100 101 return workflowDocumentInfo.isValidAction(ActionType.CANCEL); 102 } 103 104 public boolean canRecall(Document document) { 105 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 106 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 107 108 return workflowDocumentInfo.isEnroute(); 109 } 110 111 public boolean canCopy(Document document) { 112 boolean canCopy = false; 113 if (document.getAllowsCopy()) { 114 canCopy = true; 115 } 116 return canCopy; 117 } 118 119 @Override 120 public boolean canPerformRouteReport(Document document) { 121 return getParameterService().getParameterValueAsBoolean(KRADConstants.KNS_NAMESPACE, 122 KRADConstants.DetailTypes.DOCUMENT_DETAIL_TYPE, 123 KRADConstants.SystemGroupParameterNames.DEFAULT_CAN_PERFORM_ROUTE_REPORT_IND); 124 } 125 126 public boolean canAddAdhocRequests(Document document) { 127 return true; 128 } 129 130 public boolean canBlanketApprove(Document document) { 131 // check system parameter - if Y, use default workflow behavior: allow a user with the permission 132 // to perform the blanket approve action at any time 133 Boolean allowBlanketApproveNoRequest = getParameterService().getParameterValueAsBoolean( 134 KRADConstants.KNS_NAMESPACE, KRADConstants.DetailTypes.DOCUMENT_DETAIL_TYPE, 135 KRADConstants.SystemGroupParameterNames.ALLOW_ENROUTE_BLANKET_APPROVE_WITHOUT_APPROVAL_REQUEST_IND); 136 if (allowBlanketApproveNoRequest != null && allowBlanketApproveNoRequest.booleanValue()) { 137 return canEdit(document); 138 } 139 140 // otherwise, limit the display of the blanket approve button to only the initiator of the document 141 // (prior to routing) 142 WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); 143 if (canRoute(document) && StringUtils.equals(workflowDocument.getInitiatorPrincipalId(), 144 GlobalVariables.getUserSession().getPrincipalId())) { 145 return true; 146 } 147 148 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 149 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 150 151 // or to a user with an approval action request 152 if (workflowDocumentInfo.isApprovalRequested()) { 153 return true; 154 } 155 156 return false; 157 } 158 159 public boolean canApprove(Document document) { 160 return !canComplete(document); 161 } 162 163 public boolean canDisapprove(Document document) { 164 // most of the time, a person who can approve can disapprove 165 return canApprove(document); 166 } 167 168 public boolean canSendAdhocRequests(Document document) { 169 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 170 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 171 172 return !(workflowDocumentInfo.isInitiated() || workflowDocumentInfo.isSaved()); 173 } 174 175 public boolean canSendNoteFyi(Document document) { 176 return true; 177 } 178 179 public boolean canEditDocumentOverview(Document document) { 180 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 181 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 182 183 return (workflowDocumentInfo.isInitiated() || workflowDocumentInfo.isSaved()); 184 } 185 186 public boolean canFyi(Document document) { 187 return true; 188 } 189 190 public boolean canAcknowledge(Document document) { 191 return true; 192 } 193 194 public boolean canComplete(Document document) { 195 DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo = 196 getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo(); 197 198 boolean docInInit = workflowDocumentInfo.isInitiated() || workflowDocumentInfo.isSaved(); 199 boolean completionRequested = workflowDocumentInfo.isCompletionRequested(); 200 if (completionRequested && !docInInit) { 201 return true; 202 } 203 return false; 204 } 205 206 /** 207 * {@inheritDoc} 208 */ 209 @Override 210 public boolean canSuperUserTakeAction(Document document) { 211 return hasActionRequests(document) && canTakeAction(document); 212 } 213 214 /** 215 * {@inheritDoc} 216 */ 217 @Override 218 public boolean canSuperUserApprove(Document document) { 219 return canApproveOrDisapprove(document); 220 } 221 222 /** 223 * {@inheritDoc} 224 */ 225 @Override 226 public boolean canSuperUserDisapprove(Document document) { 227 return canApproveOrDisapprove(document); 228 } 229 230 /** 231 * Returns whether the {@code document} has any APPROVE or COMPLETE action requests. 232 * 233 * @param document the document to check 234 * 235 * @return true if the {@code document} has any APPROVE or COMPLETE action requests, false otherwise 236 */ 237 protected boolean hasActionRequests(Document document) { 238 boolean hasActionRequests = false; 239 240 for (ActionRequest actionRequest : document.getActionRequests()) { 241 if (StringUtils.equals(actionRequest.getActionRequested().getCode(), ActionRequestType.APPROVE.getCode()) 242 || StringUtils.equals(actionRequest.getActionRequested().getCode(), ActionRequestType.COMPLETE.getCode())) { 243 hasActionRequests = true; 244 break; 245 } 246 } 247 248 return hasActionRequests; 249 } 250 251 /** 252 * Returns whether a super user action can be taken on the {@code document}. 253 * 254 * <p> 255 * Typically, actions can only be taken on a document not in INITIATED, FINAL, or CANCELLED status. 256 * </p> 257 * 258 * @param document the document to check 259 * 260 * @return true if a super user action can be taken on the {@code document}, false otherwise 261 */ 262 protected boolean canTakeAction(Document document) { 263 String documentNumber = document.getDocumentNumber(); 264 DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(documentNumber); 265 266 return !isStateInitiatedFinalCancelled(status); 267 } 268 269 /** 270 * Returns whether a super user approve or disapprove action can be taken on the {@code document}. 271 * 272 * <p> 273 * Typically, actions can only be taken on a document not in INITIATED, SAVED, PROCESSED, DISAPPROVED, FINAL, or 274 * CANCELLED status. 275 * </p> 276 * 277 * @param document the document to check 278 * @return true if a super user approve or disapprove action can be taken on the {@code document}, false otherwise 279 */ 280 protected boolean canApproveOrDisapprove(Document document) { 281 boolean canComplete = canComplete(document); 282 String documentNumber = document.getDocumentNumber(); 283 DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(documentNumber); 284 285 return !canComplete && !isStateInitiatedFinalCancelled(status) && !isStateSaved(status) 286 && !isStateProcessedOrDisapproved(status); 287 } 288 289 /** 290 * Returns whether the {@code document} is in a INITIATED, FINAL, or CANCELLED state. 291 * 292 * @param status the document status 293 * 294 * @return true if the {@code document} is in a INITIATED, FINAL, or CANCELLED state, false otherwise 295 */ 296 protected boolean isStateInitiatedFinalCancelled(DocumentStatus status) { 297 return (StringUtils.equals(status.getCode(), DocumentStatus.INITIATED.getCode()) || 298 StringUtils.equals(status.getCode(), DocumentStatus.FINAL.getCode()) || 299 StringUtils.equals(status.getCode(), DocumentStatus.CANCELED.getCode())); 300 } 301 302 /** 303 * Returns whether the {@code document} is in a SAVED state. 304 * 305 * @param status the document status 306 * 307 * @return true if the {@code document} is in a SAVED state, false otherwise 308 */ 309 protected boolean isStateSaved(DocumentStatus status) { 310 return (StringUtils.equals(status.getCode(), DocumentStatus.SAVED.getCode())); 311 } 312 313 /** 314 * Returns whether the {@code document} is in a PROCESSED or DISAPPROVED state. 315 * 316 * @param status the document status 317 * 318 * @return true if the {@code document} is in a PROCESSED or DISAPPROVED state, false otherwise 319 */ 320 protected boolean isStateProcessedOrDisapproved(DocumentStatus status) { 321 return (StringUtils.equals(status.getCode(), DocumentStatus.PROCESSED.getCode()) || 322 StringUtils.equals(status.getCode(), DocumentStatus.DISAPPROVED.getCode())); 323 } 324 325 protected ParameterService getParameterService() { 326 if (parameterService == null) { 327 parameterService = CoreFrameworkServiceLocator.getParameterService(); 328 } 329 return parameterService; 330 } 331 332 protected DocumentRequestAuthorizationCache getDocumentRequestAuthorizationCache(Document document) { 333 if (this.documentRequestAuthorizationCache == null) { 334 this.documentRequestAuthorizationCache = new DocumentRequestAuthorizationCache(); 335 } 336 337 if (this.documentRequestAuthorizationCache.getWorkflowDocumentInfo() == null) { 338 this.documentRequestAuthorizationCache.createWorkflowDocumentInfo( 339 document.getDocumentHeader().getWorkflowDocument()); 340 } 341 342 return this.documentRequestAuthorizationCache; 343 } 344 345 /** 346 * {@inheritDoc} 347 */ 348 @Override 349 public void setDocumentRequestAuthorizationCache( 350 DocumentRequestAuthorizationCache documentRequestAuthorizationCache) { 351 this.documentRequestAuthorizationCache = documentRequestAuthorizationCache; 352 } 353}