View Javadoc
1   /**
2    * Copyright 2005-2015 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.kuali.rice.kew.api.action.ActionType;
19  import org.kuali.rice.kew.api.exception.WorkflowException;
20  import org.kuali.rice.kim.api.identity.Person;
21  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
22  import org.kuali.rice.krad.service.PessimisticLockService;
23  import org.kuali.rice.krad.uif.UifConstants;
24  import org.kuali.rice.krad.util.GlobalVariables;
25  import org.kuali.rice.krad.util.KRADConstants;
26  import org.kuali.rice.krad.web.form.DialogResponse;
27  import org.kuali.rice.krad.web.form.DocumentFormBase;
28  import org.kuali.rice.krad.data.KradDataServiceLocator;
29  import org.kuali.rice.krad.data.MaterializeOption;
30  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
31  import org.kuali.rice.krad.util.GlobalVariables;
32  import org.kuali.rice.krad.web.form.TransactionalDocumentFormBase;
33  import org.kuali.rice.krad.web.form.UifFormBase;
34  import org.springframework.web.servlet.ModelAndView;
35  
36  /**
37   * Default implementation of the transactional document controller service.
38   *
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   */
41  public class TransactionalDocumentControllerServiceImpl extends DocumentControllerServiceImpl implements TransactionalDocumentControllerService {
42  
43      private PessimisticLockService pessimisticLockService;
44  
45      /**
46       * {@inheritDoc}
47       */
48      @Override
49      public ModelAndView copy(TransactionalDocumentFormBase form) {
50          try {
51              // Load any lazy loaded data before proceeding with copy
52              KradDataServiceLocator.getDataObjectService().wrap(form.getDocument()).materializeReferencedObjectsToDepth(3,
53                      MaterializeOption.UPDATE_UPDATABLE_REFS);
54  
55              // Clones the original and detach the data
56              form.setDocument(KradDataServiceLocator.getDataObjectService().copyInstance(form.getDocument()));
57  
58              // Generate the header data after the copy
59              ((Copyable) form.getDocument()).toCopy();
60          } catch (WorkflowException e) {
61              throw new RuntimeException("Unable to copy transactional document", e);
62          }
63  
64          form.setEvaluateFlagsAndModes(true);
65          form.setCanEditView(null);
66  
67          return getModelAndViewService().getModelAndView(form);
68      }
69  
70      /**
71       * {@inheritDoc}
72       *
73       * <p>
74       * Releases the pessimistic locks before continuing.
75       * </p>
76       */
77      @Override
78      public ModelAndView cancel(UifFormBase form) {
79          ModelAndView modelAndView = super.cancel(form);
80  
81          releasePessimisticLocks((DocumentFormBase) form);
82  
83          return modelAndView;
84      }
85  
86      /**
87       * {@inheritDoc}
88       *
89       * <p>
90       * Releases the pessimistic locks before continuing.
91       * </p>
92       */
93      @Override
94      public ModelAndView route(DocumentFormBase form) {
95          ModelAndView modelAndView = super.route(form);
96  
97          releasePessimisticLocks(form);
98  
99          return modelAndView;
100     }
101 
102     /**
103      * {@inheritDoc}
104      *
105      * <p>
106      * Releases the pessimistic locks before continuing.
107      * </p>
108      */
109     @Override
110     public ModelAndView approve(DocumentFormBase form) {
111         ModelAndView modelAndView = super.approve(form);
112 
113         releasePessimisticLocks(form);
114 
115         return modelAndView;
116     }
117 
118     /**
119      * {@inheritDoc}
120      *
121      * <p>
122      * Releases the pessimistic locks before continuing.
123      * </p>
124      */
125     @Override
126     public ModelAndView disapprove(DocumentFormBase form) {
127         ModelAndView modelAndView = super.disapprove(form);
128 
129         releasePessimisticLocks(form);
130 
131         return modelAndView;
132     }
133 
134     /**
135      * {@inheritDoc}
136      *
137      * <p>
138      * Releases the pessimistic locks before continuing.
139      * </p>
140      */
141     @Override
142     public ModelAndView acknowledge(DocumentFormBase form) {
143         ModelAndView modelAndView = super.acknowledge(form);
144 
145         releasePessimisticLocks(form);
146 
147         return modelAndView;
148     }
149 
150     /**
151      * {@inheritDoc}
152      *
153      * <p>
154      * Prompts for save and releases the pessimistic locks before continuing.
155      * </p>
156      */
157     @Override
158     public ModelAndView close(DocumentFormBase form) {
159         Document document = form.getDocument();
160 
161         // only offer to save if it is a valid action
162         if (document.getDocumentHeader().getWorkflowDocument().isValidAction(ActionType.SAVE)) {
163             // initialize the dialog to prompt for save
164             DialogResponse dialogResponse = form.getDialogResponse(KRADConstants.QUESTION_ACTION_CLOSE_RESPONSE);
165 
166             if (dialogResponse == null) {
167                 return getModelAndViewService().showDialog(KRADConstants.QUESTION_ACTION_CLOSE_RESPONSE, false, form);
168             }
169 
170             // save if the user answers yes in the dialog
171             if (dialogResponse.getResponseAsBoolean()) {
172                 // get the explanation from the document and check it for sensitive data
173                 String explanation = document.getDocumentHeader().getExplanation();
174                 ModelAndView sensitiveDataDialogModelAndView = checkSensitiveDataAndWarningDialog(explanation, form);
175 
176                 // if a sensitive data warning dialog is returned then display it
177                 if (sensitiveDataDialogModelAndView != null) {
178                     return sensitiveDataDialogModelAndView;
179                 }
180 
181                 performWorkflowAction(form, UifConstants.WorkflowAction.SAVE);
182             }
183         }
184 
185         releasePessimisticLocks(form);
186 
187         return super.close(form);
188     }
189 
190     /**
191      * Releases the pessimistic locks for the current user.
192      *
193      * @param form form instance containing the transactional document data
194      */
195     protected void releasePessimisticLocks(DocumentFormBase form) {
196         Document document = form.getDocument();
197 
198         if (!document.getPessimisticLocks().isEmpty()) {
199             Person user = GlobalVariables.getUserSession().getPerson();
200             getPessimisticLockService().releaseAllLocksForUser(document.getPessimisticLocks(), user);
201             document.refreshPessimisticLocks();
202         }
203     }
204 
205     protected PessimisticLockService getPessimisticLockService() {
206         if (pessimisticLockService == null) {
207             pessimisticLockService = KRADServiceLocatorWeb.getPessimisticLockService();
208         }
209 
210         return pessimisticLockService;
211     }
212 
213     protected void setPessimisticLockService(PessimisticLockService pessimisticLockService) {
214         this.pessimisticLockService = pessimisticLockService;
215     }
216 
217 }