View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.document;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
20  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
21  import org.kuali.rice.kew.api.KewApiServiceLocator;
22  import org.kuali.rice.kew.api.WorkflowDocument;
23  import org.kuali.rice.kew.api.action.ActionRequest;
24  import org.kuali.rice.kew.api.action.ActionRequestType;
25  import org.kuali.rice.kew.api.action.ActionType;
26  import org.kuali.rice.kew.api.document.DocumentStatus;
27  import org.kuali.rice.krad.uif.view.RequestAuthorizationCache;
28  import org.kuali.rice.krad.util.GlobalVariables;
29  import org.kuali.rice.krad.util.KRADConstants;
30  import org.kuali.rice.krad.util.KRADUtils;
31  
32  import java.io.Serializable;
33  
34  /**
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  public class DocumentPresentationControllerBase implements DocumentPresentationController, Serializable {
38      private static final long serialVersionUID = -9181864754090276024L;
39  
40      private static transient ParameterService parameterService;
41  
42      private DocumentRequestAuthorizationCache documentRequestAuthorizationCache;
43  
44      public boolean canInitiate(String documentTypeName) {
45          return true;
46      }
47  
48      public boolean canEdit(Document document) {
49          boolean canEdit = false;
50  
51          DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo =
52                  getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo();
53  
54          if (workflowDocumentInfo.isInitiated()
55                  || workflowDocumentInfo.isSaved()
56                  || workflowDocumentInfo.isEnroute()
57                  || workflowDocumentInfo.isException()) {
58              canEdit = true;
59          }
60  
61          return canEdit;
62      }
63  
64      public boolean canAnnotate(Document document) {
65          return true;
66      }
67  
68      public boolean canReload(Document document) {
69          DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo =
70                  getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo();
71  
72          return (canEdit(document) && !workflowDocumentInfo.isInitiated());
73  
74      }
75  
76      public boolean canClose(Document document) {
77          return false;
78      }
79  
80      public boolean canSave(Document document) {
81          return canEdit(document);
82      }
83  
84      public boolean canRoute(Document document) {
85          boolean canRoute = false;
86  
87          DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo =
88                  getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo();
89  
90          if (workflowDocumentInfo.isInitiated() || workflowDocumentInfo.isSaved()) {
91              canRoute = true;
92          }
93  
94          return canRoute;
95      }
96  
97      public boolean canCancel(Document document) {
98          DocumentRequestAuthorizationCache.WorkflowDocumentInfo workflowDocumentInfo =
99                  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 }