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.kuali.rice.kew.api.action.ActionType; 019import org.kuali.rice.kew.api.exception.WorkflowException; 020import org.kuali.rice.kim.api.identity.Person; 021import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 022import org.kuali.rice.krad.service.PessimisticLockService; 023import org.kuali.rice.krad.uif.UifConstants; 024import org.kuali.rice.krad.util.GlobalVariables; 025import org.kuali.rice.krad.util.KRADConstants; 026import org.kuali.rice.krad.web.form.DialogResponse; 027import org.kuali.rice.krad.web.form.DocumentFormBase; 028import org.kuali.rice.krad.data.KradDataServiceLocator; 029import org.kuali.rice.krad.data.MaterializeOption; 030import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 031import org.kuali.rice.krad.util.GlobalVariables; 032import org.kuali.rice.krad.web.form.TransactionalDocumentFormBase; 033import org.kuali.rice.krad.web.form.UifFormBase; 034import org.springframework.web.servlet.ModelAndView; 035 036/** 037 * Default implementation of the transactional document controller service. 038 * 039 * @author Kuali Rice Team (rice.collab@kuali.org) 040 */ 041public class TransactionalDocumentControllerServiceImpl extends DocumentControllerServiceImpl implements TransactionalDocumentControllerService { 042 043 private PessimisticLockService pessimisticLockService; 044 045 /** 046 * {@inheritDoc} 047 */ 048 @Override 049 public ModelAndView copy(TransactionalDocumentFormBase form) { 050 try { 051 // Load any lazy loaded data before proceeding with copy 052 KradDataServiceLocator.getDataObjectService().wrap(form.getDocument()).materializeReferencedObjectsToDepth(3, 053 MaterializeOption.UPDATE_UPDATABLE_REFS); 054 055 // Clones the original and detach the data 056 form.setDocument(KradDataServiceLocator.getDataObjectService().copyInstance(form.getDocument())); 057 058 // Generate the header data after the copy 059 ((Copyable) form.getDocument()).toCopy(); 060 } catch (WorkflowException e) { 061 throw new RuntimeException("Unable to copy transactional document", e); 062 } 063 064 form.setEvaluateFlagsAndModes(true); 065 form.setCanEditView(null); 066 067 return getModelAndViewService().getModelAndView(form); 068 } 069 070 /** 071 * {@inheritDoc} 072 * 073 * <p> 074 * Releases the pessimistic locks before continuing. 075 * </p> 076 */ 077 @Override 078 public ModelAndView cancel(UifFormBase form) { 079 ModelAndView modelAndView = super.cancel(form); 080 081 releasePessimisticLocks((DocumentFormBase) form); 082 083 return modelAndView; 084 } 085 086 /** 087 * {@inheritDoc} 088 * 089 * <p> 090 * Releases the pessimistic locks before continuing. 091 * </p> 092 */ 093 @Override 094 public ModelAndView route(DocumentFormBase form) { 095 ModelAndView modelAndView = super.route(form); 096 097 releasePessimisticLocks(form); 098 099 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}